create-prisma-php-app 3.0.0-beta.9 → 3.0.0-rc.1

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.
@@ -19,6 +19,8 @@ use Lib\MainLayout;
19
19
  use Lib\PHPX\TemplateCompiler;
20
20
  use Lib\CacheHandler;
21
21
  use Lib\ErrorHandler;
22
+ use Firebase\JWT\JWT;
23
+ use Firebase\JWT\Key;
22
24
 
23
25
  final class Bootstrap
24
26
  {
@@ -66,6 +68,9 @@ final class Bootstrap
66
68
  'samesite' => 'Lax', // or 'Strict' depending on your requirements
67
69
  ]);
68
70
 
71
+ // Set a function call key as a cookie
72
+ self::functionCallNameEncrypt();
73
+
69
74
  $contentInfo = self::determineContentToInclude();
70
75
  self::$contentToInclude = $contentInfo['path'] ?? '';
71
76
  self::$layoutsToInclude = $contentInfo['layouts'] ?? [];
@@ -103,6 +108,46 @@ final class Bootstrap
103
108
  ErrorHandler::checkFatalError();
104
109
  }
105
110
 
111
+ private static function functionCallNameEncrypt(): void
112
+ {
113
+ $hmacSecret = $_ENV['FUNCTION_CALL_SECRET'] ?? '';
114
+ if ($hmacSecret === '') {
115
+ throw new RuntimeException("FUNCTION_CALL_SECRET is not set");
116
+ }
117
+
118
+ $aesKey = random_bytes(32);
119
+
120
+ $payload = [
121
+ 'k' => base64_encode($aesKey),
122
+ 'exp' => time() + 3600,
123
+ ];
124
+ $jwt = JWT::encode($payload, $hmacSecret, 'HS256');
125
+
126
+ setcookie(
127
+ 'pphp_function_call_jwt',
128
+ $jwt,
129
+ [
130
+ 'expires' => time() + 3600,
131
+ 'path' => '/',
132
+ 'secure' => true,
133
+ 'httponly' => false, // JS needs to read this
134
+ 'samesite' => 'Strict',
135
+ ]
136
+ );
137
+
138
+ setcookie(
139
+ 'pphp_function_call_key',
140
+ $hmacSecret,
141
+ [
142
+ 'expires' => time() + 3600,
143
+ 'path' => '/',
144
+ 'secure' => true,
145
+ 'httponly' => false, // JS needs to read this
146
+ 'samesite' => 'Strict',
147
+ ]
148
+ );
149
+ }
150
+
106
151
  private static function fileExistsCached(string $path): bool
107
152
  {
108
153
  if (!isset(self::$fileExistCache[$path])) {
@@ -533,35 +578,28 @@ final class Bootstrap
533
578
  return is_array($data) ? (object) $data : $data;
534
579
  }
535
580
 
536
- /**
537
- * Used specifically for wire (AJAX) calls.
538
- * Ends execution with JSON response.
539
- */
540
581
  public static function wireCallback()
541
582
  {
542
583
  try {
543
584
  $response = [
544
- 'success' => false,
545
- 'error' => 'Callback not provided',
546
- 'data' => null
585
+ 'success' => false,
586
+ 'error' => 'Callback not provided',
587
+ 'response' => null,
547
588
  ];
548
-
549
- $callbackResponse = null;
550
589
  $data = [];
551
590
 
552
591
  if (!empty($_FILES)) {
553
592
  $data = $_POST;
554
-
555
593
  foreach ($_FILES as $key => $file) {
556
594
  if (is_array($file['name'])) {
557
595
  $files = [];
558
- foreach ($file['name'] as $index => $name) {
596
+ foreach ($file['name'] as $i => $name) {
559
597
  $files[] = [
560
- 'name' => $name,
561
- 'type' => $file['type'][$index],
562
- 'tmp_name' => $file['tmp_name'][$index],
563
- 'error' => $file['error'][$index],
564
- 'size' => $file['size'][$index],
598
+ 'name' => $name,
599
+ 'type' => $file['type'][$i],
600
+ 'tmp_name' => $file['tmp_name'][$i],
601
+ 'error' => $file['error'][$i],
602
+ 'size' => $file['size'][$i],
565
603
  ];
566
604
  }
567
605
  $data[$key] = $files;
@@ -570,57 +608,96 @@ final class Bootstrap
570
608
  }
571
609
  }
572
610
  } else {
573
- $input = file_get_contents('php://input');
574
- $data = json_decode($input, true);
575
-
611
+ $raw = file_get_contents('php://input');
612
+ $data = json_decode($raw, true);
576
613
  if (json_last_error() !== JSON_ERROR_NONE) {
577
614
  $data = $_POST;
578
615
  }
579
616
  }
580
617
 
581
- if (isset($data['callback'])) {
582
- $callbackName = preg_replace('/[^a-zA-Z0-9_]/', '', $data['callback']);
618
+ if (
619
+ isset($data['callback']) &&
620
+ $data['callback'] === PrismaPHPSettings::$localStoreKey
621
+ ) {
622
+ echo json_encode([
623
+ 'success' => true,
624
+ 'response' => 'localStorage updated',
625
+ ], JSON_UNESCAPED_UNICODE);
626
+ exit;
627
+ }
583
628
 
584
- if (strpos($callbackName, '_') === 0) {
585
- $response['error'] = 'Invalid callback';
586
- } elseif (function_exists($callbackName) && is_callable($callbackName)) {
587
- $dataObject = self::convertToArrayObject($data);
629
+ if (empty($data['callback'])) {
630
+ echo json_encode($response, JSON_UNESCAPED_UNICODE);
631
+ exit;
632
+ }
588
633
 
589
- $callbackResponse = call_user_func($callbackName, $dataObject);
590
- $response = [
591
- 'success' => true,
592
- 'response' => $callbackResponse
593
- ];
594
- } else {
595
- if ($callbackName === PrismaPHPSettings::$localStoreKey) {
596
- $response = [
597
- 'success' => true,
598
- 'response' => 'localStorage updated'
599
- ];
600
- } else {
601
- $response['error'] = 'Invalid callback';
602
- }
603
- }
604
- } else {
605
- $response['error'] = 'No callback provided';
634
+ $token = $_COOKIE['pphp_function_call_jwt'] ?? null;
635
+ $jwtSecret = $_ENV['FUNCTION_CALL_SECRET'] ?? null;
636
+ if (!$token || !$jwtSecret) {
637
+ echo json_encode(['success' => false, 'error' => 'Missing session key or secret'], JSON_UNESCAPED_UNICODE);
638
+ exit;
639
+ }
640
+ try {
641
+ $decoded = JWT::decode($token, new Key($jwtSecret, 'HS256'));
642
+ } catch (Exception $e) {
643
+ echo json_encode(['success' => false, 'error' => 'Invalid session key'], JSON_UNESCAPED_UNICODE);
644
+ exit;
645
+ }
646
+ $aesKey = base64_decode($decoded->k, true);
647
+ if ($aesKey === false || strlen($aesKey) !== 32) {
648
+ echo json_encode(['success' => false, 'error' => 'Bad key length'], JSON_UNESCAPED_UNICODE);
649
+ exit;
650
+ }
651
+
652
+ $parts = explode(':', $data['callback'], 2);
653
+ if (count($parts) !== 2) {
654
+ echo json_encode(['success' => false, 'error' => 'Malformed callback payload'], JSON_UNESCAPED_UNICODE);
655
+ exit;
656
+ }
657
+ [$iv_b64, $ct_b64] = $parts;
658
+ $iv = base64_decode($iv_b64, true);
659
+ $ct = base64_decode($ct_b64, true);
660
+ if ($iv === false || strlen($iv) !== 16 || $ct === false) {
661
+ echo json_encode(['success' => false, 'error' => 'Invalid callback payload'], JSON_UNESCAPED_UNICODE);
662
+ exit;
663
+ }
664
+
665
+ $plain = openssl_decrypt($ct, 'AES-256-CBC', $aesKey, OPENSSL_RAW_DATA, $iv);
666
+ if ($plain === false) {
667
+ echo json_encode(['success' => false, 'error' => 'Decryption failed'], JSON_UNESCAPED_UNICODE);
668
+ exit;
669
+ }
670
+
671
+ $callbackName = preg_replace('/[^a-zA-Z0-9_]/', '', $plain);
672
+ if ($callbackName === '' || $callbackName[0] === '_') {
673
+ echo json_encode(['success' => false, 'error' => 'Invalid callback'], JSON_UNESCAPED_UNICODE);
674
+ exit;
606
675
  }
607
676
 
608
- if ($callbackResponse !== null || isset($response['error'])) {
609
- echo json_encode($response);
677
+ if (function_exists($callbackName) && is_callable($callbackName)) {
678
+ $obj = self::convertToArrayObject($data);
679
+ $result = call_user_func($callbackName, $obj);
680
+
681
+ if ($result !== null) {
682
+ echo json_encode([
683
+ 'success' => true,
684
+ 'response' => $result,
685
+ ], JSON_UNESCAPED_UNICODE);
686
+ }
687
+ } else {
688
+ echo json_encode(['success' => false, 'error' => 'Invalid callback'], JSON_UNESCAPED_UNICODE);
610
689
  }
690
+ exit;
611
691
  } catch (Throwable $e) {
612
- $response = [
692
+ echo json_encode([
613
693
  'success' => false,
614
- 'error' => 'Exception occurred',
694
+ 'error' => 'Exception occurred',
615
695
  'message' => htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8'),
616
- 'file' => htmlspecialchars($e->getFile(), ENT_QUOTES, 'UTF-8'),
617
- 'line' => (int) $e->getLine()
618
- ];
619
-
620
- echo json_encode($response, JSON_UNESCAPED_UNICODE);
696
+ 'file' => htmlspecialchars($e->getFile(), ENT_QUOTES, 'UTF-8'),
697
+ 'line' => $e->getLine(),
698
+ ], JSON_UNESCAPED_UNICODE);
699
+ exit;
621
700
  }
622
-
623
- exit;
624
701
  }
625
702
 
626
703
  public static function getLoadingsFiles(): string
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{execSync}from"child_process";import fs from"fs";import{fileURLToPath}from"url";import path from"path";import chalk from"chalk";import prompts from"prompts";import https from"https";import{randomBytes}from"crypto";const __filename=fileURLToPath(import.meta.url),__dirname=path.dirname(__filename);let updateAnswer=null;const nonBackendFiles=["favicon.ico","\\src\\app\\index.php","metadata.php","not-found.php","error.php"],dockerFiles=[".dockerignore","docker-compose.yml","Dockerfile","apache.conf"];function bsConfigUrls(e){const s=e.indexOf("\\htdocs\\");if(-1===s)return{bsTarget:"",bsPathRewrite:{}};const t=e.substring(0,s+"\\htdocs\\".length).replace(/\\/g,"\\\\"),n=e.replace(new RegExp(`^${t}`),"").replace(/\\/g,"/");let c=`http://localhost/${n}`;c=c.endsWith("/")?c.slice(0,-1):c;const i=c.replace(/(?<!:)(\/\/+)/g,"/"),o=n.replace(/\/\/+/g,"/");return{bsTarget:`${i}/`,bsPathRewrite:{"^/":`/${o.startsWith("/")?o.substring(1):o}/`}}}async function updatePackageJson(e,s){const t=path.join(e,"package.json");if(checkExcludeFiles(t))return;const n=JSON.parse(fs.readFileSync(t,"utf8"));n.scripts={...n.scripts,projectName:"tsx settings/project-name.ts"};let c=[];if(s.tailwindcss&&(n.scripts={...n.scripts,tailwind:"postcss src/app/css/tailwind.css -o src/app/css/styles.css --watch","tailwind:build":"postcss src/app/css/tailwind.css -o src/app/css/styles.css"},c.push("tailwind")),s.websocket&&(n.scripts={...n.scripts,websocket:"tsx settings/restart-websocket.ts"},c.push("websocket")),s.docker&&(n.scripts={...n.scripts,docker:"docker-compose up"},c.push("docker")),s.swaggerDocs){const e=s.prisma?"tsx settings/auto-swagger-docs.ts":"tsx settings/swagger-config.ts";n.scripts={...n.scripts,"create-swagger-docs":e}}let i={...n.scripts};i.browserSync="tsx settings/bs-config.ts",i["browserSync:build"]="tsx settings/build.ts",i.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,i.build=`npm-run-all${s.tailwindcss?" tailwind:build":""} browserSync:build`,n.scripts=i,n.type="module",fs.writeFileSync(t,JSON.stringify(n,null,2))}async function updateComposerJson(e){const s=path.join(e,"composer.json");if(checkExcludeFiles(s))return;let t;if(fs.existsSync(s)){{const e=fs.readFileSync(s,"utf8");t=JSON.parse(e)}t.autoload={"psr-4":{"":"src/"}},t.version="1.0.0",fs.writeFileSync(s,JSON.stringify(t,null,2))}}async function updateIndexJsForWebSocket(e,s){if(!s.websocket)return;const t=path.join(e,"src","app","js","index.js");if(checkExcludeFiles(t))return;let n=fs.readFileSync(t,"utf8");n+='\n// WebSocket initialization\nvar ws = new WebSocket("ws://localhost:8080");\n',fs.writeFileSync(t,n,"utf8")}function generateAuthSecret(){return randomBytes(33).toString("base64")}function generateHexEncodedKey(e=16){return randomBytes(e).toString("hex")}function copyRecursiveSync(e,s,t){const n=fs.existsSync(e),c=n&&fs.statSync(e);if(n&&c&&c.isDirectory()){const n=s.toLowerCase();if(!t.websocket&&n.includes("src\\lib\\websocket"))return;if(t.backendOnly&&n.includes("src\\app\\js")||t.backendOnly&&n.includes("src\\app\\css")||t.backendOnly&&n.includes("src\\app\\assets"))return;if(!t.swaggerDocs&&n.includes("src\\app\\swagger-docs"))return;const c=s.replace(/\\/g,"/");if(updateAnswer?.excludeFilePath?.includes(c))return;fs.existsSync(s)||fs.mkdirSync(s,{recursive:!0}),fs.readdirSync(e).forEach((n=>{copyRecursiveSync(path.join(e,n),path.join(s,n),t)}))}else{if(checkExcludeFiles(s))return;if(!t.tailwindcss&&(s.includes("tailwind.css")||s.includes("styles.css")))return;if(!t.websocket&&(s.includes("restart-websocket.ts")||s.includes("restart-websocket.bat")))return;if(!t.docker&&dockerFiles.some((e=>s.includes(e))))return;if(t.backendOnly&&nonBackendFiles.some((e=>s.includes(e))))return;if(!t.backendOnly&&s.includes("route.php"))return;if(t.backendOnly&&!t.swaggerDocs&&s.includes("layout.php"))return;if(!t.swaggerDocs&&s.includes("swagger-config.ts"))return;if(t.tailwindcss&&s.includes("index.css"))return;if((!t.swaggerDocs||!t.prisma)&&(s.includes("auto-swagger-docs.ts")||s.includes("prisma-schema-config.json")))return;fs.copyFileSync(e,s,0)}}async function executeCopy(e,s,t){s.forEach((({src:s,dest:n})=>{copyRecursiveSync(path.join(__dirname,s),path.join(e,n),t)}))}function modifyPostcssConfig(e){const s=path.join(e,"postcss.config.js");if(checkExcludeFiles(s))return;fs.writeFileSync(s,'export default {\n plugins: {\n "@tailwindcss/postcss": {},\n cssnano: {},\n },\n};',{flag:"w"})}function modifyLayoutPHP(e,s){const t=path.join(e,"src","app","layout.php");if(!checkExcludeFiles(t))try{let e=fs.readFileSync(t,"utf8"),n="";s.backendOnly||(s.tailwindcss||(n='\n <link href="<?= Request::baseUrl; ?>/css/index.css" rel="stylesheet" />'),n+='\n <script src="<?= Request::baseUrl; ?>/js/morphdom-umd.min.js"><\/script>\n <script src="<?= Request::baseUrl; ?>/js/json5.min.js"><\/script>\n <script src="<?= Request::baseUrl; ?>/js/index.js"><\/script>');let c="";s.backendOnly||(c=s.tailwindcss?` <link href="<?= Request::baseUrl; ?>/css/styles.css" rel="stylesheet" /> ${n}`:n),e=e.replace("</head>",`${c}\n</head>`),fs.writeFileSync(t,e,{flag:"w"})}catch(e){}}async function createOrUpdateEnvFile(e,s){const t=path.join(e,".env");checkExcludeFiles(t)||fs.writeFileSync(t,s,{flag:"w"})}function checkExcludeFiles(e){return!!updateAnswer?.isUpdate&&(updateAnswer?.excludeFilePath?.includes(e.replace(/\\/g,"/"))??!1)}async function createDirectoryStructure(e,s){const t=[{src:"/bootstrap.php",dest:"/bootstrap.php"},{src:"/.htaccess",dest:"/.htaccess"},{src:"/tsconfig.json",dest:"/tsconfig.json"},{src:"/app-gitignore",dest:"/.gitignore"}];s.tailwindcss&&t.push({src:"/postcss.config.js",dest:"/postcss.config.js"});const n=[{src:"/settings",dest:"/settings"},{src:"/src",dest:"/src"}];s.docker&&n.push({src:"/.dockerignore",dest:"/.dockerignore"},{src:"/docker-compose.yml",dest:"/docker-compose.yml"},{src:"/Dockerfile",dest:"/Dockerfile"},{src:"/apache.conf",dest:"/apache.conf"}),t.forEach((({src:s,dest:t})=>{const n=path.join(__dirname,s),c=path.join(e,t);if(checkExcludeFiles(c))return;const i=fs.readFileSync(n,"utf8");fs.writeFileSync(c,i,{flag:"w"})})),await executeCopy(e,n,s),await updatePackageJson(e,s),await updateComposerJson(e),s.backendOnly||await updateIndexJsForWebSocket(e,s),s.tailwindcss&&modifyPostcssConfig(e),(s.tailwindcss||!s.backendOnly||s.swaggerDocs)&&modifyLayoutPHP(e,s);const c=generateAuthSecret(),i=generateHexEncodedKey(),o=`# Prisma PHP Auth Secret Key\nAUTH_SECRET="${c}"\nAUTH_COOKIE_NAME="${generateHexEncodedKey(8)}"\n\n# PHPMailer\n# SMTP_HOST="smtp.gmail.com" or your SMTP host\n# SMTP_USERNAME="john.doe@gmail.com" or your SMTP username\n# SMTP_PASSWORD="123456"\n# SMTP_PORT="587" for TLS, 465 for SSL or your SMTP port\n# SMTP_ENCRYPTION="ssl" or tls\n# MAIL_FROM="john.doe@gmail.com"\n# MAIL_FROM_NAME="John Doe"\n\n# SHOW ERRORS - Set to true to show errors in the browser for development only - Change this in production to false\nSHOW_ERRORS="true"\n\n# APP TIMEZONE - Set your application timezone - Default is "UTC"\nAPP_TIMEZONE="UTC"\n\n# APP ENV - Set your application environment - Default is "development" - Change this in production to "production"\nAPP_ENV="development"\n\n# APP CACHE ENABLED - Set to true to enable caching - Default is false\nCACHE_ENABLED="false"\n# APP CACHE TTL - Set the cache time to live in seconds - Default is 600 seconds (10 minutes)\nCACHE_TTL="600"\n\n# LOCAL STORAGE KEY - Define a custom key for local storage.\n# If not set, it defaults to "pphp_local_store_59e13".\n# Spaces in the value will be replaced with underscores, and the key will be converted to lowercase automatically.\nLOCALSTORE_KEY="${i}"`;if(s.prisma){const s=`${'# Environment variables declared in this file are automatically made available to Prisma.\n# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema\n\n# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.\n# See the documentation for all the connection string options: https://pris.ly/d/connection-strings\n\nDATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"'}\n\n${o}`;await createOrUpdateEnvFile(e,s)}else await createOrUpdateEnvFile(e,o)}async function getAnswer(e={}){const s=[];e.projectName||s.push({type:"text",name:"projectName",message:"What is your project named?",initial:"my-app"}),e.backendOnly||s.push({type:"toggle",name:"backendOnly",message:`Would you like to create a ${chalk.blue("backend-only project")}?`,initial:!1,active:"Yes",inactive:"No"});const t=()=>{process.exit(0)},n=await prompts(s,{onCancel:t}),c=[];n.backendOnly||e.backendOnly?(e.swaggerDocs||c.push({type:"toggle",name:"swaggerDocs",message:`Would you like to use ${chalk.blue("Swagger Docs")}?`,initial:!1,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!0,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!0,active:"Yes",inactive:"No"}),e.docker||c.push({type:"toggle",name:"docker",message:`Would you like to use ${chalk.blue("Docker")}?`,initial:!1,active:"Yes",inactive:"No"})):(e.swaggerDocs||c.push({type:"toggle",name:"swaggerDocs",message:`Would you like to use ${chalk.blue("Swagger Docs")}?`,initial:!1,active:"Yes",inactive:"No"}),e.tailwindcss||c.push({type:"toggle",name:"tailwindcss",message:`Would you like to use ${chalk.blue("Tailwind CSS")}?`,initial:!1,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!1,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!1,active:"Yes",inactive:"No"}),e.docker||c.push({type:"toggle",name:"docker",message:`Would you like to use ${chalk.blue("Docker")}?`,initial:!1,active:"Yes",inactive:"No"}));const i=await prompts(c,{onCancel:t});return{projectName:n.projectName?String(n.projectName).trim().replace(/ /g,"-"):e.projectName??"my-app",backendOnly:n.backendOnly??e.backendOnly??!1,swaggerDocs:i.swaggerDocs??e.swaggerDocs??!1,tailwindcss:i.tailwindcss??e.tailwindcss??!1,websocket:i.websocket??e.websocket??!1,prisma:i.prisma??e.prisma??!1,docker:i.docker??e.docker??!1}}async function uninstallNpmDependencies(e,s,t=!1){s.forEach((e=>{}));const n=`npm uninstall ${t?"--save-dev":"--save"} ${s.join(" ")}`;execSync(n,{stdio:"inherit",cwd:e})}async function uninstallComposerDependencies(e,s){s.forEach((e=>{}));const t=`C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar remove ${s.join(" ")}`;execSync(t,{stdio:"inherit",cwd:e})}function fetchPackageVersion(e){return new Promise(((s,t)=>{https.get(`https://registry.npmjs.org/${e}`,(e=>{let n="";e.on("data",(e=>n+=e)),e.on("end",(()=>{try{const e=JSON.parse(n);s(e["dist-tags"].latest)}catch(e){t(new Error("Failed to parse JSON response"))}}))})).on("error",(e=>t(e)))}))}const readJsonFile=e=>{const s=fs.readFileSync(e,"utf8");return JSON.parse(s)};function compareVersions(e,s){const t=e.split(".").map(Number),n=s.split(".").map(Number);for(let e=0;e<t.length;e++){if(t[e]>n[e])return 1;if(t[e]<n[e])return-1}return 0}function getInstalledPackageVersion(e){try{const s=execSync(`npm list -g ${e} --depth=0`).toString().match(new RegExp(`${e}@(\\d+\\.\\d+\\.\\d+)`));return s?s[1]:null}catch(e){return null}}
2
+ import{execSync}from"child_process";import fs from"fs";import{fileURLToPath}from"url";import path from"path";import chalk from"chalk";import prompts from"prompts";import https from"https";import{randomBytes}from"crypto";const __filename=fileURLToPath(import.meta.url),__dirname=path.dirname(__filename);let updateAnswer=null;const nonBackendFiles=["favicon.ico","\\src\\app\\index.php","metadata.php","not-found.php","error.php"],dockerFiles=[".dockerignore","docker-compose.yml","Dockerfile","apache.conf"];function bsConfigUrls(e){const s=e.indexOf("\\htdocs\\");if(-1===s)return{bsTarget:"",bsPathRewrite:{}};const t=e.substring(0,s+"\\htdocs\\".length).replace(/\\/g,"\\\\"),n=e.replace(new RegExp(`^${t}`),"").replace(/\\/g,"/");let c=`http://localhost/${n}`;c=c.endsWith("/")?c.slice(0,-1):c;const o=c.replace(/(?<!:)(\/\/+)/g,"/"),i=n.replace(/\/\/+/g,"/");return{bsTarget:`${o}/`,bsPathRewrite:{"^/":`/${i.startsWith("/")?i.substring(1):i}/`}}}async function updatePackageJson(e,s){const t=path.join(e,"package.json");if(checkExcludeFiles(t))return;const n=JSON.parse(fs.readFileSync(t,"utf8"));n.scripts={...n.scripts,projectName:"tsx settings/project-name.ts"};let c=[];if(s.tailwindcss&&(n.scripts={...n.scripts,tailwind:"postcss src/app/css/tailwind.css -o src/app/css/styles.css --watch","tailwind:build":"postcss src/app/css/tailwind.css -o src/app/css/styles.css"},c.push("tailwind")),s.websocket&&(n.scripts={...n.scripts,websocket:"tsx settings/restart-websocket.ts"},c.push("websocket")),s.docker&&(n.scripts={...n.scripts,docker:"docker-compose up"},c.push("docker")),s.swaggerDocs){const e=s.prisma?"tsx settings/auto-swagger-docs.ts":"tsx settings/swagger-config.ts";n.scripts={...n.scripts,"create-swagger-docs":e}}let o={...n.scripts};o.browserSync="tsx settings/bs-config.ts",o["browserSync:build"]="tsx settings/build.ts",o.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,o.build=`npm-run-all${s.tailwindcss?" tailwind:build":""} browserSync:build`,n.scripts=o,n.type="module",fs.writeFileSync(t,JSON.stringify(n,null,2))}async function updateComposerJson(e){const s=path.join(e,"composer.json");if(checkExcludeFiles(s))return;let t;if(fs.existsSync(s)){{const e=fs.readFileSync(s,"utf8");t=JSON.parse(e)}t.autoload={"psr-4":{"":"src/"}},t.version="1.0.0",fs.writeFileSync(s,JSON.stringify(t,null,2))}}async function updateIndexJsForWebSocket(e,s){if(!s.websocket)return;const t=path.join(e,"src","app","js","index.js");if(checkExcludeFiles(t))return;let n=fs.readFileSync(t,"utf8");n+='\n// WebSocket initialization\nvar ws = new WebSocket("ws://localhost:8080");\n',fs.writeFileSync(t,n,"utf8")}function generateAuthSecret(){return randomBytes(33).toString("base64")}function generateHexEncodedKey(e=16){return randomBytes(e).toString("hex")}function copyRecursiveSync(e,s,t){const n=fs.existsSync(e),c=n&&fs.statSync(e);if(n&&c&&c.isDirectory()){const n=s.toLowerCase();if(!t.websocket&&n.includes("src\\lib\\websocket"))return;if(t.backendOnly&&n.includes("src\\app\\js")||t.backendOnly&&n.includes("src\\app\\css")||t.backendOnly&&n.includes("src\\app\\assets"))return;if(!t.swaggerDocs&&n.includes("src\\app\\swagger-docs"))return;const c=s.replace(/\\/g,"/");if(updateAnswer?.excludeFilePath?.includes(c))return;fs.existsSync(s)||fs.mkdirSync(s,{recursive:!0}),fs.readdirSync(e).forEach((n=>{copyRecursiveSync(path.join(e,n),path.join(s,n),t)}))}else{if(checkExcludeFiles(s))return;if(!t.tailwindcss&&(s.includes("tailwind.css")||s.includes("styles.css")))return;if(!t.websocket&&(s.includes("restart-websocket.ts")||s.includes("restart-websocket.bat")))return;if(!t.docker&&dockerFiles.some((e=>s.includes(e))))return;if(t.backendOnly&&nonBackendFiles.some((e=>s.includes(e))))return;if(!t.backendOnly&&s.includes("route.php"))return;if(t.backendOnly&&!t.swaggerDocs&&s.includes("layout.php"))return;if(!t.swaggerDocs&&s.includes("swagger-config.ts"))return;if(t.tailwindcss&&s.includes("index.css"))return;if((!t.swaggerDocs||!t.prisma)&&(s.includes("auto-swagger-docs.ts")||s.includes("prisma-schema-config.json")))return;fs.copyFileSync(e,s,0)}}async function executeCopy(e,s,t){s.forEach((({src:s,dest:n})=>{copyRecursiveSync(path.join(__dirname,s),path.join(e,n),t)}))}function modifyPostcssConfig(e){const s=path.join(e,"postcss.config.js");if(checkExcludeFiles(s))return;fs.writeFileSync(s,'export default {\n plugins: {\n "@tailwindcss/postcss": {},\n cssnano: {},\n },\n};',{flag:"w"})}function modifyLayoutPHP(e,s){const t=path.join(e,"src","app","layout.php");if(!checkExcludeFiles(t))try{let e=fs.readFileSync(t,"utf8"),n="";s.backendOnly||(s.tailwindcss||(n='\n <link href="<?= Request::baseUrl; ?>/css/index.css" rel="stylesheet" />'),n+='\n <script src="<?= Request::baseUrl; ?>/js/morphdom-umd.min.js"><\/script>\n <script src="<?= Request::baseUrl; ?>/js/json5.min.js"><\/script>\n <script src="<?= Request::baseUrl; ?>/js/index.js"><\/script>');let c="";s.backendOnly||(c=s.tailwindcss?` <link href="<?= Request::baseUrl; ?>/css/styles.css" rel="stylesheet" /> ${n}`:n),e=e.replace("</head>",`${c}\n</head>`),fs.writeFileSync(t,e,{flag:"w"})}catch(e){}}async function createOrUpdateEnvFile(e,s){const t=path.join(e,".env");checkExcludeFiles(t)||fs.writeFileSync(t,s,{flag:"w"})}function checkExcludeFiles(e){return!!updateAnswer?.isUpdate&&(updateAnswer?.excludeFilePath?.includes(e.replace(/\\/g,"/"))??!1)}async function createDirectoryStructure(e,s){const t=[{src:"/bootstrap.php",dest:"/bootstrap.php"},{src:"/.htaccess",dest:"/.htaccess"},{src:"/tsconfig.json",dest:"/tsconfig.json"},{src:"/app-gitignore",dest:"/.gitignore"}];s.tailwindcss&&t.push({src:"/postcss.config.js",dest:"/postcss.config.js"});const n=[{src:"/settings",dest:"/settings"},{src:"/src",dest:"/src"}];s.docker&&n.push({src:"/.dockerignore",dest:"/.dockerignore"},{src:"/docker-compose.yml",dest:"/docker-compose.yml"},{src:"/Dockerfile",dest:"/Dockerfile"},{src:"/apache.conf",dest:"/apache.conf"}),t.forEach((({src:s,dest:t})=>{const n=path.join(__dirname,s),c=path.join(e,t);if(checkExcludeFiles(c))return;const o=fs.readFileSync(n,"utf8");fs.writeFileSync(c,o,{flag:"w"})})),await executeCopy(e,n,s),await updatePackageJson(e,s),await updateComposerJson(e),s.backendOnly||await updateIndexJsForWebSocket(e,s),s.tailwindcss&&modifyPostcssConfig(e),(s.tailwindcss||!s.backendOnly||s.swaggerDocs)&&modifyLayoutPHP(e,s);const c=generateAuthSecret(),o=generateHexEncodedKey(),i=`# Prisma PHP Auth Secret Key\nAUTH_SECRET="${c}"\nAUTH_COOKIE_NAME="${generateHexEncodedKey(8)}"\n\n# PHPMailer\n# SMTP_HOST="smtp.gmail.com" or your SMTP host\n# SMTP_USERNAME="john.doe@gmail.com" or your SMTP username\n# SMTP_PASSWORD="123456"\n# SMTP_PORT="587" for TLS, 465 for SSL or your SMTP port\n# SMTP_ENCRYPTION="ssl" or tls\n# MAIL_FROM="john.doe@gmail.com"\n# MAIL_FROM_NAME="John Doe"\n\n# SHOW ERRORS - Set to true to show errors in the browser for development only - Change this in production to false\nSHOW_ERRORS="true"\n\n# APP TIMEZONE - Set your application timezone - Default is "UTC"\nAPP_TIMEZONE="UTC"\n\n# APP ENV - Set your application environment - Default is "development" - Change this in production to "production"\nAPP_ENV="development"\n\n# APP CACHE ENABLED - Set to true to enable caching - Default is false\nCACHE_ENABLED="false"\n# APP CACHE TTL - Set the cache time to live in seconds - Default is 600 seconds (10 minutes)\nCACHE_TTL="600"\n\n# LOCAL STORAGE KEY - Define a custom key for local storage.\n# If not set, it defaults to "pphp_local_store_59e13".\n# Spaces in the value will be replaced with underscores, and the key will be converted to lowercase automatically.\nLOCALSTORE_KEY="${o}"\n\n# FUNCTION CALL KEY - Define a custom key for function calls.\n# If not set, it defaults to "pphp_function_call_59e14".\n# Spaces in the value will be replaced with underscores, and the key will be converted to lowercase automatically.\nFUNCTION_CALL_KEY="${generateHexEncodedKey(16)}"\nFUNCTION_CALL_SECRET="${generateHexEncodedKey(32)}"`;if(s.prisma){const s=`${'# Environment variables declared in this file are automatically made available to Prisma.\n# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema\n\n# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.\n# See the documentation for all the connection string options: https://pris.ly/d/connection-strings\n\nDATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"'}\n\n${i}`;await createOrUpdateEnvFile(e,s)}else await createOrUpdateEnvFile(e,i)}async function getAnswer(e={}){const s=[];e.projectName||s.push({type:"text",name:"projectName",message:"What is your project named?",initial:"my-app"}),e.backendOnly||s.push({type:"toggle",name:"backendOnly",message:`Would you like to create a ${chalk.blue("backend-only project")}?`,initial:!1,active:"Yes",inactive:"No"});const t=()=>{process.exit(0)},n=await prompts(s,{onCancel:t}),c=[];n.backendOnly||e.backendOnly?(e.swaggerDocs||c.push({type:"toggle",name:"swaggerDocs",message:`Would you like to use ${chalk.blue("Swagger Docs")}?`,initial:!1,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!0,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!0,active:"Yes",inactive:"No"}),e.docker||c.push({type:"toggle",name:"docker",message:`Would you like to use ${chalk.blue("Docker")}?`,initial:!1,active:"Yes",inactive:"No"})):(e.swaggerDocs||c.push({type:"toggle",name:"swaggerDocs",message:`Would you like to use ${chalk.blue("Swagger Docs")}?`,initial:!1,active:"Yes",inactive:"No"}),e.tailwindcss||c.push({type:"toggle",name:"tailwindcss",message:`Would you like to use ${chalk.blue("Tailwind CSS")}?`,initial:!1,active:"Yes",inactive:"No"}),e.websocket||c.push({type:"toggle",name:"websocket",message:`Would you like to use ${chalk.blue("Websocket")}?`,initial:!1,active:"Yes",inactive:"No"}),e.prisma||c.push({type:"toggle",name:"prisma",message:`Would you like to use ${chalk.blue("Prisma PHP ORM")}?`,initial:!1,active:"Yes",inactive:"No"}),e.docker||c.push({type:"toggle",name:"docker",message:`Would you like to use ${chalk.blue("Docker")}?`,initial:!1,active:"Yes",inactive:"No"}));const o=await prompts(c,{onCancel:t});return{projectName:n.projectName?String(n.projectName).trim().replace(/ /g,"-"):e.projectName??"my-app",backendOnly:n.backendOnly??e.backendOnly??!1,swaggerDocs:o.swaggerDocs??e.swaggerDocs??!1,tailwindcss:o.tailwindcss??e.tailwindcss??!1,websocket:o.websocket??e.websocket??!1,prisma:o.prisma??e.prisma??!1,docker:o.docker??e.docker??!1}}async function uninstallNpmDependencies(e,s,t=!1){s.forEach((e=>{}));const n=`npm uninstall ${t?"--save-dev":"--save"} ${s.join(" ")}`;execSync(n,{stdio:"inherit",cwd:e})}async function uninstallComposerDependencies(e,s){s.forEach((e=>{}));const t=`C:\\xampp\\php\\php.exe C:\\ProgramData\\ComposerSetup\\bin\\composer.phar remove ${s.join(" ")}`;execSync(t,{stdio:"inherit",cwd:e})}function fetchPackageVersion(e){return new Promise(((s,t)=>{https.get(`https://registry.npmjs.org/${e}`,(e=>{let n="";e.on("data",(e=>n+=e)),e.on("end",(()=>{try{const e=JSON.parse(n);s(e["dist-tags"].latest)}catch(e){t(new Error("Failed to parse JSON response"))}}))})).on("error",(e=>t(e)))}))}const readJsonFile=e=>{const s=fs.readFileSync(e,"utf8");return JSON.parse(s)};function compareVersions(e,s){const t=e.split(".").map(Number),n=s.split(".").map(Number);for(let e=0;e<t.length;e++){if(t[e]>n[e])return 1;if(t[e]<n[e])return-1}return 0}function getInstalledPackageVersion(e){try{const s=execSync(`npm list -g ${e} --depth=0`).toString().match(new RegExp(`${e}@(\\d+\\.\\d+\\.\\d+)`));return s?s[1]:null}catch(e){return null}}
3
3
  /**
4
4
  * Install dependencies in the specified directory.
5
5
  * @param {string} baseDir - The base directory where to install the dependencies.
@@ -55,9 +55,9 @@ async function installComposerDependencies(baseDir, dependencies) {
55
55
  });
56
56
  }
57
57
  const npmPinnedVersions = {
58
- "@tailwindcss/postcss": "^4.1.7",
58
+ "@tailwindcss/postcss": "^4.1.10",
59
59
  "@types/browser-sync": "^2.29.0",
60
- "@types/node": "^22.15.19",
60
+ "@types/node": "^24.0.1",
61
61
  "@types/prompts": "^2.4.9",
62
62
  "browser-sync": "^3.0.4",
63
63
  chalk: "^5.4.1",
@@ -66,11 +66,11 @@ const npmPinnedVersions = {
66
66
  "http-proxy-middleware": "^3.0.5",
67
67
  "npm-run-all": "^4.1.5",
68
68
  "php-parser": "^3.2.3",
69
- postcss: "^8.5.3",
69
+ postcss: "^8.5.5",
70
70
  "postcss-cli": "^11.0.1",
71
71
  prompts: "^2.4.2",
72
- tailwindcss: "^4.1.7",
73
- tsx: "^4.19.4",
72
+ tailwindcss: "^4.1.10",
73
+ tsx: "^4.20.3",
74
74
  typescript: "^5.8.3",
75
75
  };
76
76
  function npmPkg(name) {
@@ -41,7 +41,7 @@ class IncludeTracker
41
41
  $html = ob_get_clean();
42
42
 
43
43
  $wrapped = self::wrapWithId($filePath, $html);
44
- $fragDom = TemplateCompiler::convertToXml($wrapped, false);
44
+ $fragDom = TemplateCompiler::convertToXml($wrapped);
45
45
 
46
46
  self::prefixInlineHandlers($fragDom);
47
47
 
@@ -16,6 +16,7 @@ use Bootstrap;
16
16
  use LibXMLError;
17
17
  use DOMXPath;
18
18
  use ReflectionClass;
19
+ use ReflectionProperty;
19
20
 
20
21
  class TemplateCompiler
21
22
  {
@@ -43,6 +44,9 @@ class TemplateCompiler
43
44
  private static array $sectionStack = [];
44
45
  private static int $compileDepth = 0;
45
46
  private static array $componentInstanceCounts = [];
47
+ private static array $reflections = [];
48
+ private static array $constructors = [];
49
+ private static array $publicProperties = [];
46
50
 
47
51
  public static function compile(string $templateContent): string
48
52
  {
@@ -96,12 +100,14 @@ class TemplateCompiler
96
100
  1
97
101
  );
98
102
 
99
- $htmlContent = preg_replace(
100
- '/<body([^>]*)>/i',
101
- '<body$1 hidden>',
102
- $htmlContent,
103
- 1
104
- );
103
+ if (!isset($_SERVER['HTTP_X_PPHP_NAVIGATION'])) {
104
+ $htmlContent = preg_replace(
105
+ '/<body([^>]*)>/i',
106
+ '<body$1 hidden>',
107
+ $htmlContent,
108
+ 1
109
+ );
110
+ }
105
111
  }
106
112
 
107
113
  $patternBodyClose = '/(<\/body\s*>)/i';
@@ -119,11 +125,9 @@ class TemplateCompiler
119
125
 
120
126
  private static function escapeAmpersands(string $content): string
121
127
  {
122
- return preg_replace_callback(
123
- '/&(.*?)/',
124
- fn($m) => preg_match('/^&(?:[a-zA-Z]+|#[0-9]+|#x[0-9A-Fa-f]+);$/', $m[0])
125
- ? $m[0]
126
- : '&amp;' . substr($m[0], 1),
128
+ return preg_replace(
129
+ '/&(?![a-zA-Z][A-Za-z0-9]*;|#[0-9]+;|#x[0-9A-Fa-f]+;)/',
130
+ '&amp;',
127
131
  $content
128
132
  );
129
133
  }
@@ -146,16 +150,15 @@ class TemplateCompiler
146
150
  );
147
151
  }
148
152
 
149
- public static function convertToXml(string $templateContent, bool $escapeAttributes = true): DOMDocument
153
+ public static function convertToXml(string $templateContent): DOMDocument
150
154
  {
155
+ $templateContent = self::protectInlineScripts($templateContent);
151
156
 
152
- if ($escapeAttributes) {
153
- $templateContent = self::escapeMustacheAngles(
154
- self::escapeAttributeAngles(
155
- self::escapeAmpersands($templateContent)
156
- )
157
- );
158
- }
157
+ $templateContent = self::escapeMustacheAngles(
158
+ self::escapeAttributeAngles(
159
+ self::escapeAmpersands($templateContent)
160
+ )
161
+ );
159
162
 
160
163
  $dom = new DOMDocument();
161
164
  libxml_use_internal_errors(true);
@@ -170,12 +173,31 @@ class TemplateCompiler
170
173
  return $dom;
171
174
  }
172
175
 
173
- /**
174
- * Extracts the inner XML of a DOMNode, including all child nodes.
175
- *
176
- * @param DOMNode $node The node from which to extract the inner XML.
177
- * @return string The inner XML as a string.
178
- */
176
+ private static function protectInlineScripts(string $html): string
177
+ {
178
+ return preg_replace_callback(
179
+ '#<script\b([^>]*?)>(.*?)</script>#is',
180
+ static function ($m) {
181
+ if (preg_match('/\bsrc\s*=/i', $m[1])) {
182
+ return $m[0];
183
+ }
184
+
185
+ if (strpos($m[2], '<![CDATA[') !== false) {
186
+ return $m[0];
187
+ }
188
+
189
+ if (preg_match('/\btype\s*=\s*(["\']?)(?!text\/|application\/javascript|module)/i', $m[1])) {
190
+ return $m[0];
191
+ }
192
+
193
+ $code = str_replace(']]>', ']]]]><![CDATA[>', $m[2]);
194
+
195
+ return "<script{$m[1]}><![CDATA[\n{$code}\n]]></script>";
196
+ },
197
+ $html
198
+ );
199
+ }
200
+
179
201
  public static function innerXml(DOMNode $node): string
180
202
  {
181
203
  if ($node instanceof DOMDocument) {
@@ -323,7 +345,7 @@ class TemplateCompiler
323
345
  $sectionId = $idx === 0 ? $baseId : "{$baseId}{$idx}";
324
346
 
325
347
  $html = $instance->render();
326
- $fragDom = self::convertToXml($html, false);
348
+ $fragDom = self::convertToXml($html);
327
349
  $xpath = new DOMXPath($fragDom);
328
350
 
329
351
  /** @var DOMElement $el */
@@ -465,6 +487,7 @@ class TemplateCompiler
465
487
  if (!isset($mapping['className'], $mapping['filePath'])) {
466
488
  throw new RuntimeException("Invalid mapping");
467
489
  }
490
+
468
491
  $className = $mapping['className'];
469
492
  $filePath = $mapping['filePath'];
470
493
 
@@ -473,16 +496,32 @@ class TemplateCompiler
473
496
  throw new RuntimeException("Class {$className} not found");
474
497
  }
475
498
 
476
- $instance = new $className($attributes);
477
- $ref = new ReflectionClass($instance);
499
+ if (!isset(self::$reflections[$className])) {
500
+ $rc = new ReflectionClass($className);
501
+ self::$reflections[$className] = $rc;
502
+ self::$constructors[$className] = $rc->getConstructor();
503
+ self::$publicProperties[$className] = array_filter(
504
+ $rc->getProperties(ReflectionProperty::IS_PUBLIC),
505
+ fn(ReflectionProperty $p) => ! $p->isStatic()
506
+ );
507
+ }
478
508
 
479
- foreach ($attributes as $key => $value) {
480
- if ($ref->hasProperty($key) && $ref->getProperty($key)->isPublic()) {
481
- $instance->$key = $value;
509
+ $ref = self::$reflections[$className];
510
+ $ctor = self::$constructors[$className];
511
+ $inst = $ref->newInstanceWithoutConstructor();
512
+
513
+ foreach (self::$publicProperties[$className] as $prop) {
514
+ $name = $prop->getName();
515
+ if (array_key_exists($name, $attributes)) {
516
+ $inst->$name = $attributes[$name];
482
517
  }
483
518
  }
484
519
 
485
- return $instance;
520
+ if ($ctor) {
521
+ $ctor->invoke($inst, $attributes);
522
+ }
523
+
524
+ return $inst;
486
525
  }
487
526
 
488
527
  protected static function initializeClassMappings(): void
@@ -510,12 +549,18 @@ class TemplateCompiler
510
549
  {
511
550
  $pairs = [];
512
551
  foreach ($attrs as $k => $v) {
513
- if ($k !== 'children') {
514
- $pairs[] = "{$k}=\"{$v}\"";
552
+ if ($k === 'children') {
553
+ continue;
515
554
  }
555
+ $pairs[] = sprintf(
556
+ '%s="%s"',
557
+ $k,
558
+ htmlspecialchars($v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')
559
+ );
516
560
  }
517
561
  $attrStr = $pairs ? ' ' . implode(' ', $pairs) : '';
518
- return in_array(strtolower($tag), self::$selfClosingTags)
562
+
563
+ return in_array(strtolower($tag), self::$selfClosingTags, true)
519
564
  ? "<{$tag}{$attrStr} />"
520
565
  : "<{$tag}{$attrStr}>{$attrs['children']}</{$tag}>";
521
566
  }
@@ -99,6 +99,13 @@ class PrismaPHPSettings
99
99
  */
100
100
  public static array $htmlEvents = [];
101
101
 
102
+ /**
103
+ * The function call key for the app.
104
+ *
105
+ * @var string
106
+ */
107
+ public static string $functionCallKey;
108
+
102
109
  public static function init(): void
103
110
  {
104
111
  self::$option = self::getPrismaSettings();
@@ -107,6 +114,7 @@ class PrismaPHPSettings
107
114
  self::$includeFiles = self::getIncludeFiles();
108
115
  self::$localStoreKey = self::getLocalStorageKey();
109
116
  self::$htmlEvents = self::getHtmlEvents();
117
+ self::$functionCallKey = self::getFunctionCallKey();
110
118
  }
111
119
 
112
120
  /**
@@ -197,4 +205,10 @@ class PrismaPHPSettings
197
205
  $events = json_decode(file_get_contents($path), true);
198
206
  return is_array($events) ? $events : [];
199
207
  }
208
+
209
+ private static function getFunctionCallKey(): string
210
+ {
211
+ $functionCallKey = $_ENV['FUNCTION_CALL_KEY'] ?? 'pphp_function_call_59e14';
212
+ return strtolower(preg_replace('/\s+/', '_', trim($functionCallKey)));
213
+ }
200
214
  }
@@ -1 +1 @@
1
- (()=>{const e=EventTarget.prototype.addEventListener,t=EventTarget.prototype.removeEventListener,s=new Map,n=new Set(["wheel","mousewheel","touchstart","touchmove","touchend","touchcancel","scroll"]);EventTarget.prototype.addEventListener=function(t,r,i){let a=i;n.has(t)&&(void 0===a?a={passive:!0}:"boolean"==typeof a?a={capture:a,passive:!0}:a&&void 0===a.passive&&(a={...a,passive:!0})),s.has(this)||s.set(this,new Map);const o=s.get(this),c=o.get(t)||new Set;c.add(r),o.set(t,c),e.call(this,t,r,a)},EventTarget.prototype.removeEventListener=function(e,n,r){if(s.has(this)&&s.get(this).has(e)){const t=s.get(this).get(e);t.delete(n),0===t.size&&s.get(this).delete(e)}t.call(this,e,n,r)},EventTarget.prototype.removeAllEventListeners=function(e){if(!s.has(this))return;const n=s.get(this).get(e);n&&(n.forEach((s=>{t.call(this,e,s)})),s.get(this).delete(e))}})();class PPHP{props={};_isNavigating=!1;_responseData=null;_elementState={checkedElements:new Set};_activeAbortController=null;_reservedWords;_declaredStateRoots=new Set;_arrayMethodCache=new WeakMap;_scopedKeys=new Map;_updateScheduled=!1;_pendingBindings=new Set;_effects=new Set;_pendingEffects=new Set;_processedPhpSections=new Set;_processedPhpScripts=new WeakSet;_bindings=[];_templateStore=new WeakMap;_inlineDepth=0;_activeSection=null;_inlineModuleFns=new Map;_proxyCache=new WeakMap;_rawProps={};_refs=new Map;_wheelHandlersStashed=!1;_evaluatorCache=new Map;_depsCache=new Map;_dirtyDeps=new Set;_handlerCache=new Map;_handlerProxyCache=new WeakMap;_sharedStateMap=new Map;_sectionParentMap=new Map;_eventHandlers;_redirectRegex=/redirect_7F834\s*=\s*(\/[^\s]*)/;_assignmentRe=/^\s*[\w.]+\s*=(?!=)/;_mustacheRe=/\{\{\s*([\s\S]+?)\s*\}\}/gu;_mutators;_boolAttrs=new Set(["allowfullscreen","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","itemscope","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected","truespeed"]);static _instance;static _effectCleanups;static debounceTimers=new Map;static _cancelableEvents=new Set(["click","submit","change"]);static _mustacheTest=/\{\{\s*[\s\S]+?\s*\}\}/;static _mustachePattern=/\{\{\s*([\s\S]+?)\s*\}\}/g;static _passiveEvents=new Set(["wheel","mousewheel","touchstart","touchmove","touchend","touchcancel","scroll"]);static _bareCallRe=/^[A-Za-z_$]\w*\s*\(.*\)$/;static _autoPrefixes=new Set;constructor(){const e=Object.getOwnPropertyNames(HTMLElement.prototype).filter((e=>e.startsWith("on"))),t=Object.getOwnPropertyNames(Document.prototype).filter((e=>e.startsWith("on"))),s=Object.getOwnPropertyNames(Window.prototype).filter((e=>e.startsWith("on")));this._eventHandlers=new Set([...e,...t,...s].map((e=>e.toLowerCase()))),this._reservedWords=new Set(["null","undefined","true","false","await","break","case","catch","class","const","continue","debugger","default","delete","do","else","export","extends","finally","for","function","if","import","in","instanceof","let","new","return","super","switch","this","throw","try","typeof","var","void","while","with","yield","async","await","implements","interface","event","NaN","Infinity","Number","String","Boolean","Object","Array","Function","Date","RegExp","Error","JSON","Math","Map","Set"]),this._mutators=new Set(["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"]),this.handlePopState(),this._proxyCache=new WeakMap,this._evaluatorCache.clear(),this._depsCache.clear(),this.props=this.makeReactive(this._rawProps),this.scheduleInitialHydration()}static get instance(){return PPHP._instance||(PPHP._instance=new PPHP),PPHP._instance}scheduleInitialHydration(){const e=async()=>{await this.initRefs(),await this.processInlineModuleScripts(),await this.initializeAllReferencedProps(),await this.initBindings(),await this.initLoopBindings(),this.attachWireFunctionEvents(),this._bindings.forEach((e=>e.update())),document.body.removeAttribute("hidden")};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e,{once:!0}):e()}getScopeId(e){for(;e;){const t=e.getAttribute("pp-phpx-id");if(t)return t;const s=e.getAttribute("pp-section-id");if(s)return s;e=e.parentElement}return null}getSectionId(e){for(;e;){const t=e.getAttribute("pp-section-id");if(t)return t;e=e.parentElement}return null}getPhpxId(e){for(;e;){const t=e.getAttribute("pp-phpx-id");if(t)return t;e=e.parentElement}return null}getPhpxParentId(e){if(!e)return null;let t=e,s=null;for(;t&&!s;)s=t.getAttribute("pp-phpx-id"),s||(t=t.parentElement);let n=t?.parentElement;for(;n;){const e=n.getAttribute("pp-phpx-id");if(e&&e!==s)return e;n=n.parentElement}return null}ref(e,t){const s=this._activeSection;let n=[];if(s&&(n=this._sectionRefs.get(s)?.get(e)??[]),0===n.length&&(n=this._refs.get(e)??[]),null!=t){const s=n[t];if(!s)throw new Error(`pphp.ref('${e}', ${t}) — no element at that index`);return s}if(0===n.length)throw new Error(`pphp.ref('${e}') failed — no element was found`);return 1===n.length?n[0]:n}effect(e,t){const s=this._currentScopeId(),n=Array.isArray(t),r=n?t:[],i=n&&0===r.length,a=r.map((e=>{if("function"==typeof e&&e.__pphp_key)return e.__pphp_key;if("string"!=typeof e)return"";if(e.includes("_"))return e;for(const[t,s]of this._scopedKeys)if(s.has(e))return`${t}_${e}`;if(s){const t=this._sharedStateMap.get(s);if(t?.has(e)){const t=this._sectionParentMap.get(s);return t?`${t}_${e}`:e}}return e})).filter(Boolean),o=new Set(a),c=new Map;for(const e of a){const t=this.getNested(this.props,e);c.set(e,t)}let l=0;PPHP._effectCleanups||(PPHP._effectCleanups=new WeakMap);const h=PPHP._effectCleanups,p=()=>{const t=h.get(p);if(t){try{t()}catch(e){console.error("cleanup error:",e)}h.delete(p)}if(++l>50)throw new Error("PPHP: effect ran >50 times — possible loop");if(!i&&a.length>0){let e=!1;for(const t of a){if(this.getNested(this.props,t)!==c.get(t)){e=!0;break}}if(!e)return;for(const e of a)c.set(e,this.getNested(this.props,e))}try{const t=e();"function"==typeof t&&h.set(p,t)}catch(e){console.error("effect error:",e)}};Object.assign(p,{__deps:o,__sectionId:s??null,__static:i});try{const t=e();"function"==typeof t&&h.set(p,t)}catch(e){console.error("effect error (initial):",e)}for(const e of a)c.set(e,this.getNested(this.props,e));const u=n&&this._inlineDepth>0?this._pendingEffects:this._effects;return i?this._effects.add(p):u.add(p),()=>{const e=h.get(p);if(e){try{e()}catch(e){console.error("cleanup error:",e)}h.delete(p)}this._effects.delete(p),this._pendingEffects.delete(p)}}resetProps(){Object.keys(this._rawProps).forEach((e=>{if(window.hasOwnProperty(e)){const t=Object.getOwnPropertyDescriptor(window,e);t&&t.configurable&&delete window[e]}})),this._rawProps={},this._proxyCache=new WeakMap,this._templateStore=new WeakMap,this._arrayMethodCache=new WeakMap,this._handlerProxyCache=new WeakMap,this._depsCache.clear(),this._evaluatorCache.clear(),this._handlerCache.clear(),this._sharedStateMap.clear(),this._sectionParentMap.clear(),this._processedPhpSections.clear(),this._processedPhpScripts=new WeakSet,this._scopedKeys=new Map,this._declaredStateRoots.clear(),this._inlineModuleFns.clear(),PPHP._autoPrefixes.clear(),this._bindings=[],this._pendingBindings.clear(),this._effects.clear(),this._pendingEffects.clear(),this._refs.clear(),this._sectionRefs.clear(),this.clearHandlerCaches(),this.props=this.makeReactive(this._rawProps)}async initMakeReactive(){await this.initRefs(),await this.initializeAllReferencedProps(),await this.initBindings(),await this.initLoopBindings(),this.attachWireFunctionEvents(),this._bindings.forEach((e=>e.update())),document.body.removeAttribute("hidden")}async initLoopBindings(){document.querySelectorAll("[pp-for]").forEach((e=>this.registerLoop(e)))}registerLoop(e){const t=this.getScopeId(e),s=e.getAttribute("pp-for").trim(),[n,r]=s.split(/\s+in\s+/),[i,a]=n.replace(/^\(|\)$/g,"").split(",").map((e=>e.trim())),o=t?`${t}_${i}`:i,c=a?t?`${t}_${a}`:a:null,l=t?r.replace(/\b([A-Za-z_$]\w*)\b/g,((e,s,n,r)=>"."===r[n-1]||this._reservedWords.has(s)||s.startsWith(t+"_")?e:`${t}_${s}`)):r,h=e.parentNode,p=document.createComment("pp-for");h.insertBefore(p,e),h.removeChild(e);const u=this.makeSafeEvaluator(l),d=e=>t?e.replace(new RegExp(`\\b${i}\\b`,"g"),o).replace(a?new RegExp(`\\b${a}\\b`,"g"):/$^/,c??""):e,f=this.extractDependencies(l),m=l.match(/^\s*([A-Za-z_$]\w*)\s*\(/);if(m){const e=m[1],t=this._inlineModuleFns.get(e);if("function"==typeof t){const e=t.toString();this.extractDependencies(e).forEach((e=>f.add(e.split(".")[0])))}}this._bindings.push({dependencies:f,update:()=>{const t=document.activeElement;let s=null,n=null;if((t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement)&&h.contains(t)){const e=t.closest("[key]");s=e?.getAttribute("key")??null,n=t.selectionStart}for(let e=p.nextSibling;e&&e.nodeType!==Node.COMMENT_NODE;){const t=e.nextSibling;h.removeChild(e),e=t}const r=this.getOrCreateProxy(this.props),l=u(r);Array.isArray(l)||console.warn("[pp-for] expected an Array but got:",l);if((Array.isArray(l)?l:[]).forEach(((t,s)=>{this.props[o]=t,c&&(this.props[c]=s);const n=e.content.cloneNode(!0),r=document.createTreeWalker(n,NodeFilter.SHOW_TEXT);for(let e;e=r.nextNode();)e.nodeValue=(e.nodeValue||"").replace(PPHP._mustachePattern,((e,t)=>{try{const e=d(t);return this.formatValue(this.makeSafeEvaluator(e)(this.props))}catch{return""}}));n.querySelectorAll("*").forEach((e=>{for(const{name:t,value:s}of Array.from(e.attributes)){if("pp-bind"===t){const t=d(s),n=this.makeSafeEvaluator(t)(this.props);e.textContent=this.formatValue(n);continue}if("pp-bind-expr"===t){const t=this.decodeEntities?this.decodeEntities(s):s,n=d(t),r=this.makeSafeEvaluator(n)(this.props);e.textContent=this.formatValue(r);continue}const n=t.match(/^pp-bind-(.+)$/);if(!n)continue;const r=n[1],i=d(s),a=this.makeSafeEvaluator(i)(this.props);if(this._boolAttrs.has(r)){const t=!!a;e[r]=t,t?e.setAttribute(r,""):e.removeAttribute(r)}else r in e?e[r]=a:e.setAttribute(r,String(a))}})),n.querySelectorAll("*").forEach((e=>{for(const{name:t,value:s}of Array.from(e.attributes)){const n=t.match(/^pp-bind-(.+)$/);if(!n)continue;const r=n[1],i=d(s),a=this.makeSafeEvaluator(i)(this.props);if(this._boolAttrs.has(r)){const t=!!a;e[r]=t,t?e.setAttribute(r,""):e.removeAttribute(r)}else r in e?e[r]=a:e.setAttribute(r,String(a))}})),n.querySelectorAll("*").forEach((e=>{Array.from(e.attributes).forEach((n=>{const r=n.name.startsWith("on"),o=n.name.startsWith("pp-inc-on"),c=n.name.startsWith("pp-comp-on");if(!r&&!o&&!c)return;let l=n.value;/\b(?:i|idx)\b/.test(l)&&(l=((e,t)=>e.replace(/\[\s*(?:i|idx)\s*\]/g,`[${t}]`).replace(/(^|[^\w$])(?:i|idx)(?!\w)/g,((e,s)=>s+t)))(l,s));const h=new RegExp(`\\b${i}\\b`,"g");var p;if(l=l.replace(h,(p=t,JSON.stringify(p))),a){const e=new RegExp(`\\b${a}\\b`,"g");l=l.replace(e,String(s))}e.setAttribute(n.name,l)}))})),h.insertBefore(n,p.nextSibling)})),null!==s){const e=h.querySelector(`[key="${s}"]`),t=e?.querySelector("input,textarea");if((t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement)&&(t.focus({preventScroll:!0}),null!==n)){const e=Math.min(n,t.value.length);t.setSelectionRange(e,e)}}this.attachWireFunctionEvents()}})}_sectionRefs=new Map;async initRefs(){document.querySelectorAll("[pp-ref]").forEach((e=>{const t=e.getAttribute("pp-ref"),s=this.getScopeId(e)??"__global__",n=this._sectionRefs.get(s)??new Map,r=n.get(t)??[];r.push(e),n.set(t,r),this._sectionRefs.set(s,n);const i=this._refs.get(t)??[];i.push(e),this._refs.set(t,i),e.removeAttribute("pp-ref")}))}scheduleBindingUpdate(e){this._pendingBindings.add(e),this._updateScheduled||(this._updateScheduled=!0,requestAnimationFrame((()=>{this.flushBindings()})))}makeReactive(e,t=[]){const s=this._proxyCache.get(e);if(s)return s;if(e instanceof Map||e instanceof Set||"object"!=typeof e||null===e)return e;const n=this,r=new Proxy(e,{get(e,s,r){const i=Reflect.get(e,s,r);if(Array.isArray(e)&&"string"==typeof s&&n._mutators.has(s)){let a=n._arrayMethodCache.get(e);if(a||(a=new Map,n._arrayMethodCache.set(e,a)),!a.has(s)){const e=i.bind(r),o=t.join("."),c=function(...t){const s=e(...t);return queueMicrotask((()=>{n._bindings.forEach((e=>{e.dependencies.has(o)&&n.scheduleBindingUpdate(e)}))})),s};a.set(s,c)}return a.get(s)}return null!==i&&"object"==typeof i?n.makeReactive(i,[...t,s]):i},set(e,s,r,i){let a=r;null!==r&&"object"==typeof r&&(a=n.makeReactive(r,[...t,s]));const o=e[s],c=Reflect.set(e,s,a,i);if(o===a)return c;const l=[...t,s].join(".");return n._bindings.forEach((e=>{for(const t of e.dependencies)if(l===t||l.startsWith(t+".")||t.startsWith(l+".")){n.scheduleBindingUpdate(e);break}})),c}});return this._proxyCache.set(e,r),r}makeAttrTemplateUpdater(e,t,s,n){let r=this._templateStore.get(e);r||(r=new Map,this._templateStore.set(e,r)),r.has(t)||r.set(t,e.getAttribute(t)||"");const i=n??r.get(t)??"";return(i.match(this._mustacheRe)||[]).forEach((e=>{this.extractDependencies(e).forEach((e=>s.add(e)))})),()=>{try{const s=i.replace(this._mustacheRe,((e,t)=>{try{const e=this.makeSafeEvaluator(t);return this.formatValue(e(this.props))}catch(e){return console.error("Error token:",t,e),""}}));e.getAttribute(t)!==s&&e.setAttribute(t,s)}catch(e){console.error(`Error evaluating the template for attribute "${t}". Please check the template syntax and dependencies.`,e)}}}makePrimitiveUpdater(e,t,s){const n={};return this._eventHandlers.forEach((e=>{if(e.startsWith("on")){const t=e.slice(2);n[t]=t}})),n.value="input",n.checked="change",()=>{try{const r=s(this.props),i=this.formatValue(r);let a=!1;if("value"===t){const t=e;"value"in e&&t.value!==i?(t.value=i,a=!0):"value"in e||(e.setAttribute("value",i),a=!0)}else{const t=e,s="true"===i;"checked"in e&&t.checked!==s?(t.checked=s,a=!0):"checked"in e||(e.setAttribute("checked",i),a=!0)}if(!a||e instanceof HTMLInputElement&&("hidden"===e.type||e.disabled||e.readOnly))return;const o=n[t]||t,c="click"===o?new MouseEvent(o,{bubbles:!0,cancelable:!0}):new Event(o,{bubbles:!0});e.dispatchEvent(c)}catch(e){console.error(`Error evaluating attribute "${t}":`,e)}}}formatValue(e){return null!==e&&"object"==typeof e&&1===Object.keys(e).length&&Object.prototype.hasOwnProperty.call(e,"value")?this.formatValue(e.value):"function"==typeof e?"":"boolean"==typeof e?e?"true":"false":Array.isArray(e)?e.map((e=>"object"==typeof e?JSON.stringify(e):String(e))).join(", "):e&&"object"==typeof e?Object.keys(e).length?JSON.stringify(e,null,2):"":e?.toString()??""}registerBinding(e,t,s="text",n){if(this._assignmentRe.test(t))return;const r=this.getScopeId(e);let i=t;if(r){const e=this._scopedKeys.get(r)||new Set,s=this._sharedStateMap.get(r)||new Set,n=this._sectionParentMap.get(r);i=t.replace(/\b([A-Za-z_$][\w$]*)\b/g,((t,i,a,o)=>{if("."===o[a-1]||this._reservedWords.has(i))return t;if(s.has(i))return n?`${n}_${i}`:i;if(e.has(i)||this.hasNested(this.props,`${r}_${i}`))return`${r}_${i}`;let c=this._sectionParentMap.get(r)||null;for(;c;){if(this._scopedKeys.get(c)?.has(i)||this.hasNested(this.props,`${c}_${i}`))return`${c}_${i}`;c=this._sectionParentMap.get(c)||null}return t}))}const a=new Set([...this.extractDependencies(i)].map((e=>e.split(".")[0])).filter((e=>e in this.props&&!this._reservedWords.has(e)))),o=this.makeSafeEvaluator(i);if("value"===n||"checked"===n){const t=this.makePrimitiveUpdater(e,n,o);return void this._bindings.push({dependencies:a,update:t})}if(n){const s=n.toLowerCase();if(this._boolAttrs.has(s)){e.removeAttribute(s);const r=()=>{try{const t=!!o(this.props);e[n]!==t&&(e[n]=t),t?e.setAttribute(s,""):e.removeAttribute(s)}catch(e){console.error(`PPHP: error evaluating boolean attribute ${n}="${t}"`,e)}};return void this._bindings.push({dependencies:a,update:r})}const c=e.getAttribute(n)??"";if(this._mustacheRe.test(i)||this._mustacheRe.test(c)){const t=this._scopedKeys.get(r??"")??new Set,s=this._sharedStateMap.get(r??"")??new Set,i=this._sectionParentMap.get(r??"")??null,o=c.replace(this._mustacheRe,((e,n)=>`{{ ${n.replace(/\b([A-Za-z_$][\w$]*)\b/g,((e,n,a,o)=>{if("."===o[a-1]||this._reservedWords.has(n))return e;if(s.has(n))return i?`${i}_${n}`:n;if(t.has(n))return`${r}_${n}`;let c=this._sectionParentMap.get(r??"")||null;for(;c;){if(this._scopedKeys.get(c)?.has(n)||this.hasNested(this.props,`${c}_${n}`))return`${c}_${n}`;c=this._sectionParentMap.get(c)||null}return e}))} }}`)),l=this.makeAttrTemplateUpdater(e,n,a,o);return void this._bindings.push({dependencies:a,update:l})}const l=()=>{try{const t=o(this.props),s=this.formatValue(t);n in e&&(e[n]=s),e.setAttribute(n,s)}catch(e){console.error(`Error evaluating attribute ${n}="${t}"`,e)}};return void this._bindings.push({dependencies:a,update:l})}const c={text(e,t){e.textContent!==t&&(e.textContent=t)},value(e,t){e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement?e.value!==t&&(e.value=t):e.setAttribute("value",t)},checked(e,t){e instanceof HTMLInputElement?e.checked="true"===t:e.setAttribute("checked",t)},attr(e,t){e.setAttribute("attr",t)}};this._bindings.push({dependencies:a,update:()=>{try{const t=o(this.props),n=this.formatValue(t);c[s](e,n)}catch(e){console.error(`Error evaluating expression "${t}"`,e)}}})}makeSafeEvaluator(e){const t=e.trim(),s=`\n try {\n with (ctx) {\n ${/^\s*[\w.]+\s*=(?!=)/.test(t)?`${t}; return "";`:`return (${t});`}\n }\n } catch {\n return "";\n }\n `;let n;try{n=new Function("ctx",s)}catch(t){const s=JSON.stringify(e);n=new Function("ctx",`try { return ${s}; } catch { return ""; }`)}return e=>{try{const t=n(e);return null==t?"":t}catch{return""}}}async initBindings(){this._bindings=[];const e=new WeakSet;document.body.querySelectorAll("[pp-if]").forEach((t=>{if(e.has(t))return;const s=[];let n=t;for(;n;){if(n.hasAttribute("pp-if"))s.push({el:n,expr:n.getAttribute("pp-if")});else if(n.hasAttribute("pp-elseif"))s.push({el:n,expr:n.getAttribute("pp-elseif")});else{if(!n.hasAttribute("pp-else"))break;s.push({el:n,expr:null})}e.add(n),n=n.nextElementSibling}s.forEach((e=>{if(null!==e.expr){const t=e.expr.replace(/^{\s*|\s*}$/g,"");e.deps=this.extractDependencies(t);const s=this.makeSafeEvaluator(t);e.evaluate=()=>!!s(this.props)}}));const r=new Set;s.forEach((e=>e.deps?.forEach((e=>r.add(e)))));this._bindings.push({dependencies:r,update:()=>{let e=!1;for(const{el:t,expr:n,evaluate:r}of s)!e&&null!==n&&r()?(t.removeAttribute("hidden"),e=!0):e||null!==n?t.setAttribute("hidden",""):(t.removeAttribute("hidden"),e=!0)}})})),document.body.querySelectorAll("*").forEach((e=>{["pp-bind","pp-bind-expr"].forEach((t=>{const s=e.getAttribute(t);s&&this.registerBinding(e,s,"text")})),Array.from(e.attributes).forEach((t=>{const s=t.name.toLowerCase(),n=t.value.trim();this._boolAttrs.has(s)&&!t.name.startsWith("pp-bind-")&&/^[A-Za-z_$][\w$]*$/.test(n)&&(e.removeAttribute(t.name),this.registerBinding(e,n,"text",s))})),Array.from(e.attributes).forEach((t=>{if(!t.name.startsWith("pp-bind-"))return;if("pp-bind"===t.name||"pp-bind-expr"===t.name||"pp-bind-spread"===t.name)return;const s=this.decodeEntities(t.value).replace(/^{{\s*|\s*}}$/g,"");let n=t.name.replace(/^(pp-bind-)+/,"");const r="value"===n?"value":"checked"===n?"checked":"text";this.registerBinding(e,s,r,n)})),Array.from(e.attributes).forEach((t=>{if("pp-bind-spread"!==t.name)return;const s=this.decodeEntities(t.value).split(",").map((e=>e.trim())).filter(Boolean),n=new Set;s.forEach((e=>n.add(e.split(".")[0])));const r=new Set;this._bindings.push({dependencies:n,update:()=>{try{const t={};s.forEach((e=>{const s=this.getNested(this.props,e)??{};Object.assign(t,s)})),r.forEach((s=>{s in t||e.hasAttribute(s)||(e.removeAttribute(s),r.delete(s))})),Object.entries(t).forEach((([t,s])=>{if(!r.has(t)&&e.hasAttribute(t))return;if(!1===s||null==s)return void(r.has(t)&&(e.removeAttribute(t),r.delete(t)));const n="object"==typeof s?JSON.stringify(s):String(s);e.getAttribute(t)!==n&&e.setAttribute(t,n),r.add(t)}))}catch(e){console.error("pp-spread error:",e)}}})}))}))}callInlineModule(e,...t){const s=this._inlineModuleFns.get(e);if(!s)throw new Error(`PPHP: no inline module named "${e}"`);return s(...t)}async processInlineModuleScripts(){this._inlineDepth++,this._sharedStateMap.clear(),this._sectionParentMap.clear();try{const e=Array.from(document.body.querySelectorAll('script[type="text/php"]:not([src])')).filter((e=>{const t=this.getScopeId(e);return t?!this._processedPhpSections.has(t):!this._processedPhpScripts.has(e)}));if(!e.length)return;document.querySelectorAll("[pp-section-id]").forEach((e=>{const t=e.getAttribute("pp-section-id"),s=this.findParentSectionId(e);s&&this._sectionParentMap.set(t,s)})),document.querySelectorAll("[pp-phpx-id]").forEach((e=>{const t=e.getAttribute("pp-phpx-id"),s=this.findParentSectionId(e);s&&this._sectionParentMap.set(t,s)}));const t=this.sortScriptsByDependency(e),s={};for(const e of t){const t=this.getScopeId(e);if(!t)continue;const n=e.textContent||"";for(const[,e]of[...n.matchAll(/export\s+const\s+([A-Za-z_$]\w*)/g),...n.matchAll(/export\s+function\s+([A-Za-z_$]\w*)/g)])s[e]=t}for(const[e,t]of Object.entries(s))this._scopedKeys.has(t)||this._scopedKeys.set(t,new Set),this._scopedKeys.get(t).add(e);for(const e of t){const t=this.getScopeId(e);let n=(e.textContent||"").trim();if(n=this.decodeEntities(n),n=this.stripComments(n),n=this.transformStateDeclarations(n,t),t){const e=this._sectionParentMap.get(t)??null,s=t+"_",r=e?e+"_":"",i=new Set;if(this._declaredStateRoots.forEach((e=>{e.startsWith(s)?i.add(e.slice(s.length)):r&&e.startsWith(r)?i.add(e.slice(r.length)):e.includes("_")||i.add(e)})),i.size){let e="";for(const a of i){const i=this.hasNested(pphp.props,s+a)?s+a:this.hasNested(pphp.props,r+a)?r+a:a,o="set"+a[0].toUpperCase()+a.slice(1),c=t?`${t}_${a}`:a,l=t?`${t}_${o}`:o;new RegExp(`\\b(?:const|let|var)\\s+\\[?\\s*${a}\\b`).test(n)||(e+=`\n const ${a} = (() => {\n const fn = () => pphp.props.${i};\n fn.__pphp_key = '${i}';\n Object.defineProperty(fn, 'value', {\n get(){ return pphp.props.${i}; },\n set(v){ pphp.props.${i} = v; }\n });\n return fn;\n })();\n const ${o} = v => {\n pphp.props.${i} = typeof v === 'function' ? v(pphp.props.${i}) : v;\n };\n pphp._inlineModuleFns.set('${c}', ${a});\n pphp._inlineModuleFns.set('${l}', ${o});\n `)}n=e+"\n"+n}}const r=this.extractSetters(n,t);if(r.length){n+="\n\n";for(const e of r){n+=`pphp._inlineModuleFns.set('${t?`${t}_${e}`:e}', ${e});\n`}}if(t){const e=this._sectionParentMap.get(t)??null,s=e?e+"_":"";n=n.replace(/(\bpphp\.state\(\s*['"])([^'"]+)(['"])/g,((e,n,r,i)=>r.startsWith(t+"_")||s&&r.startsWith(s)||!r.includes("_")?n+r+i:n+`${t}_${r}`+i))}n=n.replace(/\b([A-Za-z_$]\w*)\s*\(/g,((e,t,n,r)=>{const i=r.slice(Math.max(0,n-20),n);if(/\b(?:function|export\s+function)\s*$/.test(i.trim()))return e;const a=s[t];return a?`${a}_${t}(`:e}));const i=new Blob([n],{type:"application/javascript"}),a=URL.createObjectURL(i),o=PPHP.prototype._currentScopeId;t&&(PPHP.prototype._currentScopeId=()=>t);try{const e=await import(a);for(const[s,n]of Object.entries(e))if("function"==typeof n){const e=t?`${t}_${s}`:s;this._inlineModuleFns.set(e,n)}}catch(e){console.error("Inline module import failed:",e)}finally{PPHP.prototype._currentScopeId=o,URL.revokeObjectURL(a),t?this._processedPhpSections.add(t):this._processedPhpScripts.add(e)}}}finally{this._inlineDepth--,0===this._inlineDepth&&requestAnimationFrame((()=>{this._pendingEffects.forEach((e=>this._effects.add(e))),this._pendingEffects.clear()}))}}stripComments(e){let t="",s=0,n=!1,r="",i=!1;for(;s<e.length;){const a=e[s],o=e[s+1];if(i||"'"!==a&&'"'!==a&&"`"!==a||"\\"===e[s-1])if(n)t+=a,s++;else if(i||"/"!==a||"*"!==o)if(i)"*"===a&&"/"===o?(i=!1,s+=2):s++;else if("/"!==a||"/"!==o)t+=a,s++;else for(;s<e.length&&"\n"!==e[s];)s++;else i=!0,s+=2;else n=!n,r=n?a:"",t+=a,s++}return t}findParentSectionId(e){const t=e.parentElement?.closest("[pp-section-id]");return t?t.getAttribute("pp-section-id"):null}extractSetters(e,t){const s=[],n=/\[\s*([A-Za-z_$]\w*)\s*,\s*([A-Za-z_$]\w*)\s*\]\s*=\s*pphp\.state\(/g;let r;for(;null!==(r=n.exec(e));){const[,,e]=r,n=r[1];t&&this._sharedStateMap.get(t)?.has(n)||s.push(e)}return s}transformStateDeclarations(e,t){return e=(e=(e=e.replace(/(\b(?:const|let|var)\s+\[\s*)([A-Za-z_$]\w*)\s*,\s*([A-Za-z_$]\w*)\s*(\]\s*=\s*pphp\.state\s*\(\s*)/g,((e,s,n,r,i)=>t&&this._sharedStateMap.get(t)?.has(n)?e:`${s}${n}, ${r}${i}'${n}', `))).replace(/(\b(?:const|let|var)\s+\[\s*)([A-Za-z_$]\w*)\s*(\]\s*=\s*pphp\.state\s*\(\s*)/g,((e,s,n,r)=>t&&this._sharedStateMap.get(t)?.has(n)?e:`${s}${n}${r}'${n}', `))).replace(/(\b(?:const|let|var)\s+)([A-Za-z_$]\w*)(\s*=\s*pphp\.state\s*\(\s*)/g,((e,s,n,r)=>t&&this._sharedStateMap.get(t)?.has(n)?e:`${s}[${n}] = pphp.state('${n}', `))}sortScriptsByDependency(e){const t=new Map;for(const s of e){const e=this.getScopeId(s);t.has(e)||t.set(e,[]),t.get(e).push(s)}const s=[],n=new Set,r=e=>{if(!e)return[];const t=this._sectionParentMap.get(e);if(t)return[t];const s=this._sharedStateMap.get(e);return s&&s.size>0?[t||null]:[]},i=e=>{if(n.has(e))return;for(const t of r(e))i(t);const a=t.get(e)||[];s.push(...a),n.add(e)};i(null);for(const e of t.keys())null!==e&&i(e);return s}flushBindings(){const e=new Set(this._dirtyDeps);this._pendingBindings.forEach((t=>{t.dependencies.forEach((t=>e.add(t))),t.update()})),this._pendingBindings.clear(),this._dirtyDeps.clear(),this._updateScheduled=!1,this._effects.forEach((t=>{if(t.__static)return;const s=t.__deps||new Set;if(0===s.size||[...s].some((t=>e.has(t)))){const e=this._activeSection;this._activeSection=t.__sectionId??null;try{t()}catch(e){console.error("effect error:",e)}this._activeSection=e}}))}scheduleFlush(){this._updateScheduled||(this._updateScheduled=!0,requestAnimationFrame((()=>{this._updateScheduled=!1,this.flushBindings()})))}scopeKey(e){const t=this._currentScopeId();if(!t)return e;const s=this._sharedStateMap.get(t);if(s?.has(e)){const s=this._sectionParentMap.get(t);return s?`${s}_${e}`:e}return e.startsWith(`${t}_`)?e:`${t}_${e}`}_currentScopeId(){const e=document.currentScript;return this.getScopeId(e)}getNested(e,t){return t.split(".").reduce(((e,t)=>e?e[t]:void 0),e)}setNested(e,t,s){const n=t.split("."),r=n.pop();n.reduce(((e,t)=>e[t]??={}),e)[r]=s}hasNested(e,t){return void 0!==this.getNested(e,t)}state(e,t){if("string"!=typeof e||""===e.trim())throw new Error("PPHP.state: missing or invalid key—make sure your build-time injector ran and you wrote `const [foo, setFoo] = pphp.state(0)` so it became `pphp.state('foo', 0)`.");arguments.length<2&&(t=void 0);const s=this._currentScopeId(),n=e;if(this._reservedWords.has(n))throw new Error(`'${n}' is reserved – choose another state key.`);const r=this.scopeKey(n);this._declaredStateRoots.add(r),s&&(this._scopedKeys.has(s)||this._scopedKeys.set(s,new Set),this._scopedKeys.get(s).add(n)),this.hasNested(pphp.props,r)||this.setNested(pphp.props,r,t);const i=()=>this.getNested(pphp.props,r),a=e=>{const t=i(),s="function"==typeof e?e(t):e;this.setNested(pphp.props,r,s),this._dirtyDeps.add(r.split(".")[0]),this.scheduleFlush()},o=()=>i();Object.defineProperty(o,"value",{get:()=>i(),set:e=>a(e)}),Object.defineProperties(o,{valueOf:{value:()=>i()},toString:{value:()=>String(i())}}),o.__pphp_key=r;const c=i();if(null===c||"object"!=typeof c)return[o,a];return[new Proxy(o,{apply:(e,t,s)=>Reflect.apply(e,t,s),get(e,t,s){if("value"===t)return i();if(t in e)return Reflect.get(e,t,s);return i()[t]},set(e,t,s){if("value"===t)return a(s),!0;return i()[t]=s,!0},has(e,t){if("value"===t||t in o)return!0;return t in i()}}),a]}static _isBuiltIn=(()=>{const e=new Map,t=[Object.prototype,Function.prototype,Array.prototype,String.prototype,Number.prototype,Boolean.prototype,Date.prototype,RegExp.prototype,Map.prototype,Set.prototype,WeakMap.prototype,WeakSet.prototype,Error.prototype,Promise.prototype];return s=>{const n=e.get(s);if(void 0!==n)return n;const r=s in globalThis||t.some((e=>s in e));return e.set(s,r),r}})();extractDependencies(e){const t=e.trim();if(this.isPlainText(t))return new Set;let s=e.replace(/\?\./g,".");const n=new Set,r=/(?:^|[^\w$])(?:\(\s*([^)]*?)\s*\)|([A-Za-z_$][\w$]*))\s*=>/g;for(let e;e=r.exec(s);){(e[1]??e[2]??"").split(",").map((e=>e.trim())).filter(Boolean).forEach((e=>n.add(e)))}const i=/function\s*(?:[A-Za-z_$][\w$]*\s*)?\(\s*([^)]*?)\s*\)/g;for(let e;e=i.exec(s);)e[1].split(",").map((e=>e.trim())).filter(Boolean).forEach((e=>n.add(e)));const a=e=>{let t="",s=0;for(;s<e.length;)if("`"===e[s])for(s++;s<e.length;)if("\\"===e[s])s+=2;else if("$"===e[s]&&"{"===e[s+1]){s+=2;let n=1;const r=s;for(;s<e.length&&n>0;)"{"===e[s]?n++:"}"===e[s]&&n--,s++;const i=e.slice(r,s-1);t+=a(i)+" "}else{if("`"===e[s]){s++;break}s++}else t+=e[s++];return t};s=a(s),s=s.replace(/(['"])(?:\\.|[^\\])*?\1/g,""),s=s.replace(/\/(?:\\.|[^\/\\])+\/[gimsuy]*/g,"");const o=new Set,c=/\b[A-Za-z_$]\w*(?:\.[A-Za-z_$]\w*)*\b/g;for(const t of s.match(c)??[]){const[s,...r]=t.split(".");n.has(s)||(0===r.length&&PPHP._isBuiltIn(s)&&new RegExp(`\\.${s}\\b`).test(e)||o.add(t))}return o}isPlainText(e){const t=e.trim();if(/^['"`]/.test(t))return!1;return![/[+\-*/%=<>!&|?:]/,/\.\w+/,/\[\s*\w+\s*\]/,/\(\s*[^)]*\s*\)/,/=>/,/\b(true|false|null|undefined|typeof|new|delete|void|in|of|instanceof)\b/,/\?\./,/\?\?/,/\.\.\./,/\{[^}]*\}/,/\[[^\]]*\]/].some((e=>e.test(t)))&&(!!t.includes(" ")&&(!/\w+\.\w+/.test(t)&&!/\w+\[\w+\]/.test(t)))}async initializeAllReferencedProps(){const e=PPHP._mustachePattern,t=PPHP._mustacheTest,s=this.props,n=new Set,r=(e,t)=>{if(this.hasNested(this.props,t))return t;const s=e.getAttribute("pp-section-id"),n=this.getScopeId(e.parentElement);return s??n?`${s??n}_${t}`:t},i=(()=>{const e=new Set([...Object.getOwnPropertyNames(String.prototype),...Object.getOwnPropertyNames(Array.prototype),...Object.getOwnPropertyNames(Number.prototype),...Object.getOwnPropertyNames(Boolean.prototype),...Object.getOwnPropertyNames(Object.prototype),...Object.getOwnPropertyNames(Date.prototype),...Object.getOwnPropertyNames(RegExp.prototype)]);return t=>e.has(t)})(),a=(e,t)=>{const[s,a,...o]=t.split(".");if(this._reservedWords.has(s))return void console.warn(`Invalid path “${t}” – “${s}” is a reserved word.`);if(PPHP._isBuiltIn(s)&&console.warn(`Path “${t}” shadows the built-in “${s}”. It will be stored in pphp.props.`),a&&i(a))return void n.add(r(e,s));const c=r(e,s);n.add(a?`${c}.${[a,...o].join(".")}`:c)};for(const s of document.body.getElementsByTagName("*"))for(const{name:n,value:r}of Array.from(s.attributes))if(r){if(t.test(r))for(const t of r.matchAll(e))this.extractDependencies(t[1]).forEach((e=>a(s,e)));"pp-if"!==n&&"pp-elseif"!==n||this.extractDependencies(r).forEach((e=>a(s,e))),n.startsWith("pp-bind")&&this.extractDependencies(r).forEach((e=>a(s,e)))}const o=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT,{acceptNode:e=>t.test(e.nodeValue??"")?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT});for(let t;t=o.nextNode();){const s=t.parentElement;for(const n of t.nodeValue.matchAll(e))this.extractDependencies(n[1]).forEach((e=>a(s,e)))}const c=Array.from(n).sort(((e,t)=>t.split(".").length-e.split(".").length));for(const e of c){const t=e.split(".");let n=s;for(let e=0;e<t.length;e++){const s=t[e],r=e===t.length-1,i=0===e,a=t.slice(0,e+1).join(".");i&&PPHP._isBuiltIn(s)&&console.warn(`Root “${s}” shadows the built-in. The placeholder will still be created in pphp.props.`),s in n&&(r||null!=n[s]&&"object"==typeof n[s])||r&&this._declaredStateRoots.has(a)||(n[s]=r?void 0:{}),n=n[s]}}}setNestedProperty(e,t,s){const n=t.split(".");let r=e;for(let e=0;e<n.length-1;e++)n[e]in r||(r[n[e]]={}),r=r[n[e]];r[n[n.length-1]]=s}attachWireFunctionEvents(){this.handleHiddenAttribute(),this.handleAnchorTag();const e=e=>Array.from(this._eventHandlers).map((t=>`[${e}${t}]`)),t=[...e(""),...e("pp-inc-"),...e("data-pp-child-"),...e("data-pp-parent-")].flat().join(","),s=document.body.querySelectorAll(t);for(const e of s){const t=this.getSectionId(e),s=this.getPhpxId(e),n=this.getPhpxParentId(e);t&&PPHP._autoPrefixes.add(`${t}_`),s&&PPHP._autoPrefixes.add(`${s}_`),n&&PPHP._autoPrefixes.add(`${n}_`);for(const r of this._eventHandlers){const i=r,a=`pp-inc-${r}`,o=`data-pp-child-${r}`,c=`data-pp-parent-${r}`,l=e.getAttribute(i),h=e.getAttribute(a),p=e.getAttribute(o),u=e.getAttribute(c),d=l?this.decodeEntities(l).trim():"",f=h?this.decodeEntities(h).trim():"",m=p?this.decodeEntities(p).trim():"",g=u?this.decodeEntities(u).trim():"";if(!(d||f||m||g))continue;const y=[];if(d&&y.push(this.unwrapArrowBody(this.buildHandlerFromRawBody(d,null))),f&&y.push(this.unwrapArrowBody(this.buildHandlerFromRawBody(f,t))),m&&y.push(this.unwrapArrowBody(this.buildHandlerFromRawBody(m,s))),g){const e=n||t||null;y.push(this.unwrapArrowBody(this.buildHandlerFromRawBody(g,e)))}const b=`(event) => { ${[...new Set(y)].join(" ")} }`;[i,a,o,c].forEach((t=>e.removeAttribute(t)));const S=r.slice(2);e.removeAllEventListeners(S),e instanceof HTMLInputElement&&this.handleInputAppendParams(e,S),this.handleDebounce(e,S,b)}}}alreadyScoped(e,t){const s=`${t}_${e}`;return this._scopedKeys.get(t)?.has(s)??!1}prefixFunctionCalls(e,t){return e.replace(/\b([A-Za-z_$][\w$]*)\s*\(/g,((e,s)=>this._reservedWords.has(s)||s.startsWith(`${t}_`)?e:this.alreadyScoped(s,t)?`${t}_${s}(`:e))}prefixIds(e,t,s=new Set){let n="",r=0,i=(e=this.prefixFunctionCalls(e,t)).length,a=!1,o=!1,c=!1;for(;r<i;){const l=e[r];if("'"!==l||o||c||"\\"===e[r-1])if('"'!==l||a||c||"\\"===e[r-1])if("`"!==l||a||o||"\\"===e[r-1])if(a||o||c)n+=l,r++;else if(/[A-Za-z_$]/.test(l)){let a=r+1;for(;a<i&&/[\w$]/.test(e[a]);)a++;const o=e.slice(r,a),c=e[r-1]??"",l=this._reservedWords.has(o),h="."===c;n+=!(o.startsWith(`${t}_`)||h||l||s.has(o))?`${t}_${o}`:o,r=a}else n+=l,r++;else c=!c,n+=l,r++;else o=!o,n+=l,r++;else a=!a,n+=l,r++}return n}decodeEntities=e=>{const t=document.createElement("textarea");t.innerHTML=e;let s=t.value;for(;s.includes("&");){t.innerHTML=s;const e=t.value;if(e===s)break;s=e}return s};shouldPrefixForSection(e,t){if(!e||!t)return!1;const s=this.getSectionStateKeys(t);if(!s||0===s.size)return!1;const n=this.extractFunctionCalls(e);for(const e of n)if(this.isStateFunctionForSection(e,s))return!0;const r=this.extractVariableAssignments(e);for(const e of r)if(s.has(e))return!0;return!1}getSectionStateKeys(e){const t=this._scopedKeys.get(e);if(!t)return null;const s=new Set;for(const e of t){const t=e.includes("_")?e.split("_").pop():e;s.add(t)}return s}extractFunctionCalls(e){const t=[],s=/\b([A-Za-z_$][\w$]*)\s*\(/g;let n;for(;null!==(n=s.exec(e));)t.push(n[1]);return t}extractVariableAssignments(e){const t=[],s=/\b([A-Za-z_$][\w$]*)\s*=/g;let n;for(;null!==(n=s.exec(e));){const s=e[n.index-1],r=e[n.index+n[0].length];"="!==s&&"="!==r&&t.push(n[1])}return t}isStateFunctionForSection(e,t){const s=e.match(/^set([A-Z][a-zA-Z]*)$/);if(s){const e=s[1].charAt(0).toLowerCase()+s[1].slice(1);return t.has(e)}const n=e.match(/^toggle([A-Z][a-zA-Z]*)$/);if(n){const e=n[1].charAt(0).toLowerCase()+n[1].slice(1);return t.has(e)}return t.has(e)}unwrapArrowBody=e=>{if(!e.trim())return"";const t=e.match(/^\s*(?:\([\w\s,]*\)|[A-Za-z_$][\w$]*)\s*=>\s*\{([\s\S]*)\}\s*$/);if(t){let e=t[1].trim();return e&&!e.endsWith(";")&&(e+=";"),e}const s=e.match(/^\s*(?:\([\w\s,]*\)|[A-Za-z_$][\w$]*)\s*=>\s*/);if(s){let t=e.substring(s[0].length).trim();return t&&!t.endsWith(";")&&(t+=";"),t}let n=e.trim();return n&&!n.endsWith(";")&&(n+=";"),n};buildHandlerFromRawBody(e,t){const{normalized:s,originalParam:n}=this.normalizeToArrow(e),r=this.renameEventParam(s,n),i=this.replaceThisReferences(r);return t?this.prefixBareIdentifiers(i,t):i}replaceThisReferences(e){return e.replace(/\bthis\./g,"event.target.")}isBareCall(e){return!e.includes("=>")&&PPHP._bareCallRe.test(e)&&!/^[A-Za-z_$]\w*_/.test(e)}normalizeToArrow(e){const t=e.match(/^\s*(?:\([\w\s,]*\)|[A-Za-z_$][\w$]*)\s*=>/);if(!t)return{normalized:`() => { ${e} }`,originalParam:null};const s=t[0].replace(/\s*=>\s*$/,"").trim().replace(/^\(|\)$/g,"").trim();return{normalized:e,originalParam:/^[A-Za-z_$]\w*$/.test(s)?s:null}}renameEventParam(e,t){if(!t||"event"===t)return e;const s=new RegExp(`\\b${this.escapeRegex(t)}\\b`,"g");return e.replace(s,((e,t,s)=>{const n=s[t-1],r=s[t+e.length];return n&&/[\w$]/.test(n)||r&&/[\w$]/.test(r)?e:"event"}))}escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}prefixBareIdentifiers(e,t){const s=e.indexOf("=>");if(-1!==s){const n=e.slice(0,s+2),r=e.slice(s+2);return n+this.prefixIds(r,t,new Set(["event"]))}const n=this.prefixIds(e,t,new Set(["event"]));return/^[A-Za-z_$].*\)$/.test(n.trim())?`() => ${n}`:`(event) => { ${n}; }`}async handleDebounce(e,t,s){const n=e.getAttribute("pp-debounce"),r=n?this.parseTime(n):0,i=e.getAttribute("pp-before-request")??"",a=e.getAttribute("pp-after-request")??"",o=PPHP._cancelableEvents,c=async n=>{o.has(t)&&n.cancelable&&n.preventDefault();try{const t=this.getScopeId(e);if(i){const s=t?`${t}_${i}`:i;await this.invokeHandler(e,s,n)}if(await this.invokeHandler(e,s,n),a&&!a.startsWith("@close")){const s=t?`${t}_${a}`:a;await this.invokeHandler(e,s,n)}this.handlerAutofocusAttribute()}catch(e){console.error("Error in debounced handler:",e)}},l={passive:PPHP._passiveEvents.has(t)&&!o.has(t)},h=`${t}::${e.__pphpId||e.tagName}`,p=e=>{if(r>0){const t=PPHP.debounceTimers.get(h);t&&clearTimeout(t);const s=setTimeout((()=>{PPHP.debounceTimers.delete(h),c(e)}),r);PPHP.debounceTimers.set(h,s)}else c(e)};e instanceof HTMLFormElement&&"submit"===t?e.addEventListener("submit",(e=>{e.cancelable&&e.preventDefault(),p(e)}),l):e.addEventListener(t,p,l)}debounce(e,t=300,s=!1){let n;return function(...r){const i=this;n&&clearTimeout(n),n=setTimeout((()=>{n=null,s||e.apply(i,r)}),t),s&&!n&&e.apply(i,r)}}handlerAutofocusAttribute(){const e=document.querySelector("dialog[open]");let t=null;if(e&&(t=e.querySelector("[pp-autofocus]")),t||(t=document.querySelector("[pp-autofocus]")),!t)return;const s=t.getAttribute("pp-autofocus");if(!this.isJsonLike(s))return;const n=this.parseJson(s);requestAnimationFrame((()=>{t.focus(),(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement)&&"function"==typeof this.setCursorPosition&&(t instanceof HTMLInputElement&&"number"===t.type?(t.type="text",this.setCursorPosition(t,n),t.type="number"):this.setCursorPosition(t,n))}))}async invokeHandler(e,t,s){this._activeSection=this.getScopeId(e);try{const n=t.trim();let r=this._handlerCache.get(n);r||(r=this.parseHandler(n),this._handlerCache.set(n,r)),await this.executeHandler(r,e,s,n)}catch(s){this.handleInvokeError(s,t,e)}finally{this.scheduleFlush()}}parseHandler(e){const t=e.replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").replace(/\s+/g," ").trim();if(this.isArrowFunction(t))return this.parseArrowFunction(t);const s=t.match(/^(\w+(?:\.\w+)*)\s*\(\s*(.*?)\s*\)$/s);if(s)return{type:"call",name:s[1],args:s[2],isAsync:this.isAsyncFunction(s[1])};const n=t.match(/^(\w+)$/);return n?{type:"simple",name:n[1],isAsync:this.isAsyncFunction(n[1])}:{type:"complex",body:t,isAsync:!1}}isArrowFunction(e){let t=!1,s="",n=0;for(let r=0;r<e.length-1;r++){const i=e[r],a=e[r+1];if(t||'"'!==i&&"'"!==i&&"`"!==i){if(t&&i===s&&"\\"!==e[r-1])t=!1,s="";else if(!t&&("("===i&&n++,")"===i&&n--,"="===i&&">"===a&&n>=0))return!0}else t=!0,s=i}return!1}parseArrowFunction(e){const t=this.findArrowIndex(e);let s=e.substring(t+2).trim();return s.startsWith("{")&&s.endsWith("}")&&(s=s.slice(1,-1).trim()),{type:"arrow",body:s,isAsync:e.includes("async")||this.containsAwait(s)}}findArrowIndex(e){let t=!1,s="";for(let n=0;n<e.length-1;n++){const r=e[n],i=e[n+1];if(t||'"'!==r&&"'"!==r&&"`"!==r){if(t&&r===s&&"\\"!==e[n-1])t=!1;else if(!t&&"="===r&&">"===i)return n}else t=!0,s=r}return-1}async executeArrowHandler(e,t,s){const n=this.parseStatements(e.body);let r=!1;for(const e of n)await this.executeSingleStatement(e,t,s)&&(r=!0);r||await this.executeDynamic(e.body,t,s)}async executeComplexHandler(e,t,s){await this.executeDynamic(e.body,t,s)}parseStatements(e){const t=[];let s="",n=0,r=!1,i="";for(let a=0;a<e.length;a++){const o=e[a];r||'"'!==o&&"'"!==o&&"`"!==o?r&&o===i&&"\\"!==e[a-1]&&(r=!1,i=""):(r=!0,i=o),r||("("!==o&&"{"!==o&&"["!==o||n++,")"!==o&&"}"!==o&&"]"!==o||n--,";"!==o||0!==n)?s+=o:s.trim()&&(t.push(s.trim()),s="")}return s.trim()&&t.push(s.trim()),t}async executeInlineModule(e,t,s,n,r){if(t&&t.trim())if(this.isJsonLike(t)){const r=this.parseJson(t);null!==r&&"object"==typeof r?await this.callInlineModule(e,{...r,element:s,event:n}):await this.callInlineModule(e,r)}else try{const s=this.getOrCreateEvaluator(t)(this.props);await this.callInlineModule(e,s)}catch{await this.callInlineModule(e,{element:s,event:n})}else await this.handleParsedCallback(s,r,n)}async executeSingleStatement(e,t,s){const n=e.trim();if(!n)return!1;const r=n.match(/^\(\s*\)\s*=>\s*(.+)$/);if(r)return await this.executeSingleStatement(r[1],t,s);if(/^\s*(if|for|while|switch|try|return|throw|var|let|const|function|class)\b/.test(n))return await this.executeDynamic(n,t,s),!0;const i=n.match(/^(\w+)\s*\(\s*(.*?)\s*\)$/s);if(i){const[,e,r]=i,a=this.resolveFunctionName(e);if(a&&this._inlineModuleFns.has(a))return await this.executeInlineModule(a,r,t,s,n),!0;if(a){const e=globalThis[a];if("function"==typeof e)return await this.executeGlobalFunction(e,r,t,s),!0}return await this.handleParsedCallback(t,n,s),!0}const a=n.match(/^(\w+)$/);if(a){const e=a[1],n=this.resolveFunctionName(e);if(n&&this._inlineModuleFns.has(n))return await this.handleParsedCallback(t,`${n}()`,s),!0;if(n){const e=globalThis[n];if("function"==typeof e)return e.call(globalThis,s),!0}return await this.handleParsedCallback(t,`${e}()`,s),!0}return await this.executeDynamic(n,t,s),!0}async executeCallHandler(e,t,s,n){const{name:r,args:i}=e,a=this.resolveFunctionName(r);if(a){if(this._inlineModuleFns.has(a))return void await this.executeInlineModule(a,i||"",t,s,n);const e=globalThis[a];if("function"==typeof e)return void await this.executeGlobalFunction(e,i||"",t,s)}await this.handleParsedCallback(t,n,s)}resolveFunctionName(e){if(this._inlineModuleFns.has(e))return e;if(!e.includes("_")&&"function"==typeof globalThis[e])return e;if(e.includes("_")){const[t,...s]=e.split("_"),n=s.join("_"),r=this._sectionParentMap.get(t);if(r){const e=`${r}_${n}`;if(this._inlineModuleFns.has(e))return e}if(this._inlineModuleFns.has(n))return n;if("function"==typeof globalThis[n])return n}return null}async executeSimpleHandler(e,t,s){const{name:n}=e,r=this.resolveFunctionName(n);if(r){if(this._inlineModuleFns.has(r))return void await this.handleParsedCallback(t,`${r}()`,s);const e=globalThis[r];if("function"==typeof e)return void e.call(globalThis,s)}await this.handleParsedCallback(t,`${n}()`,s)}async executeHandler(e,t,s,n){switch(e.type){case"arrow":await this.executeArrowHandler(e,t,s);break;case"call":await this.executeCallHandler(e,t,s,n);break;case"simple":await this.executeSimpleHandler(e,t,s);break;case"complex":await this.executeComplexHandler(e,t,s);break;default:await this.handleParsedCallback(t,n,s)}}async executeGlobalFunction(e,t,s,n){if(t.trim())if(this.isJsonLike(t)){const r=this.parseJson(t)??{};e.call(globalThis,{...r,element:s,event:n})}else{const r=this.getOrCreateProxy(this.props);new Function("event","proxy","props","fn",`with (proxy) { return fn(${t}); }`).call(s,n,r,this.props,e)}else e.call(globalThis,n)}async executeDynamic(e,t,s){const n=this.getOrCreateProxy(this.props);let r=e;this._activeSection&&(r=this.prefixFunctionCalls(e,this._activeSection));const i=new Function("event","proxy","props",`\n with (proxy) {\n ${r}\n }`);await i.call(t,s,n,this.props)}getOrCreateEvaluator(e){let t=this._evaluatorCache.get(e);return t||(t=this.makeSafeEvaluator(e),this._evaluatorCache.set(e,t)),t}getOrCreateProxy(e){let t=this._handlerProxyCache.get(e);return t||(t=this.createHandlerProxy(e),this._handlerProxyCache.set(e,t)),t}createHandlerProxy(e){const t=this._inlineModuleFns;return new Proxy(e,{get(e,s,n){if("string"==typeof s){if(t.has(s))return t.get(s);if(s in e){const t=Reflect.get(e,s,n),r=globalThis[s];if(!(null==t||"object"==typeof t&&0===Object.keys(t).length||PPHP._isBuiltIn(s)&&typeof t!=typeof r))return t}if(s in globalThis){const e=globalThis[s];return"function"==typeof e&&/^[a-z]/.test(s)?e.bind(globalThis):e}}return Reflect.get(e,s,n)},set:(e,t,s,n)=>Reflect.set(e,t,s,n),has:(e,s)=>"string"==typeof s&&t.has(s)||s in e||s in globalThis})}isAsyncFunction(e){const t=this._inlineModuleFns.get(e)||globalThis[e];return t&&("AsyncFunction"===t.constructor.name||t.toString().includes("async "))}containsAwait(e){return/\bawait\s+/.test(e)}handleInvokeError(e,t,s){const n=e instanceof Error?e.message:String(e),r=s.tagName+(s.id?`#${s.id}`:"");console.error(`Handler execution failed on ${r}:\nHandler: "${t}"\nError: ${n}`,e),s.dispatchEvent(new CustomEvent("pphp:handler-error",{detail:{handler:t,error:e,element:s},bubbles:!0}))}clearHandlerCaches(){this._handlerCache.clear(),this._evaluatorCache.clear()}async handleParsedCallback(e,t,s){const{funcName:n,data:r}=this.parseCallback(e,t);if(!n)return;const i=Array.isArray(n)?n:[n];let a;for(const e of i){const t=this._inlineModuleFns.get(e);if("function"==typeof t){a=t;break}const s=this[e];if("function"==typeof s){a=s;break}const n=window[e];if("function"==typeof n){a=n;break}}if(a){const t=e.hasAttribute("pp-after-request"),n=Array.isArray(r.args)?r.args:[],i=this._responseData?this.parseJson(this._responseData):{response:this._responseData};let o={args:n,element:e,data:r,event:s};return t&&(o={...o,...i}),void await a.call(this,o)}this._responseData=null,this._responseData=await this.handleUndefinedFunction(e,Array.isArray(n)?n[0]:n,r)}stripAutoPrefix(e){for(const t of PPHP._autoPrefixes)if(e.startsWith(t))return e.slice(t.length);return e}async handleUndefinedFunction(e,t,s){const n=this.stripAutoPrefix(t),r={callback:n,...s},i=this.createFetchOptions(r),a=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});try{this.saveElementOriginalState(e),this.handleSuspenseElement(e);const t=new URL(window.location.href);let r="",o="",c={success:!1};const l=e.querySelector("input[type='file']");if(l){if(r=await this.fetchFileWithData(t.href,n,l,s),o=this.extractJson(r)||"",o)try{c=this.parseJson(o)}catch(e){console.error("Error parsing JSON response. Please ensure the response is in valid JSON format.",e)}}else{const e=await this.fetch(t.href,i);if(r=await e.text(),this.getRedirectUrl(r))return void await this.redirect(this.getRedirectUrl(r)||"");if(o=this.extractJson(r)||"",o)try{c=this.parseJson(o)}catch(e){console.error("Error parsing JSON response. Please ensure the response is in valid JSON format.",e)}}const h=e.getAttribute("pp-before-request")||"",p=e.getAttribute("pp-after-request")||"";if((h||p&&c.success)&&this.restoreSuspenseElement(e),h||p){let e="";if(c.success){e=r.replace(o,"")}else e=r;if(this.appendAfterbegin(e),!p&&!c.success)return}if(p&&c.success){this.handleAfterRequest(p,o);const e=r.replace(o,"");return this.appendAfterbegin(e),o}if("@close"===p)return c.success?o:void 0;const u=await this.fetch(t.href,a),d=await u.text();if(this.getRedirectUrl(d))return void await this.redirect(this.getRedirectUrl(d)||"");await this.handleResponseRedirectOrUpdate(r,d,o,c)}catch(e){console.error(`Error handling undefined function "${n}". Please ensure the function is defined and accessible.`,e)}}handleAfterRequest(e,t){if(!this.isJsonLike(e))return;const s=this.parseJson(e),n=t?this.parseJson(t):null,r=s.targets;Array.isArray(r)&&r.forEach((e=>{const{id:t,...s}=e,r=document.querySelector(t);let i={};if(n){for(const t in s)if(s.hasOwnProperty(t))switch(t){case"innerHTML":case"outerHTML":case"textContent":case"innerText":"response"===s[t]&&(i[t]=e.responseKey?n[e.responseKey]:n.response);break;default:i[t]=s[t]}}else i=s;r&&this.updateElementAttributes(r,i)}))}sanitizePassiveHandlers(e){return e.replace(/\s+onwheel\s*=\s*(['"])([\s\S]*?)\1/gi,((e,t,s)=>` data-onwheel-code="${encodeURIComponent(s)}"`)).replace(/\s+onmousewheel\s*=\s*(['"])[\s\S]*?\1/gi,"")}handlePassiveWheelStashes(e){(e instanceof Document?e.body:e).querySelectorAll("[data-onwheel-code]").forEach((e=>{let t=decodeURIComponent(e.dataset.onwheelCode||"").trim();delete e.dataset.onwheelCode,e.onwheel=null;const s=this.getScopeId(e);if(s){const e=t.indexOf("=>");if(e>=0){const n=t.slice(0,e+2),r=t.slice(e+2);t=n+this.prefixIds(r,s)}else t=this.prefixIds(t,s)}e.removeAllEventListeners("wheel"),this.handleDebounce(e,"wheel",t)}))}async handleResponseRedirectOrUpdate(e,t,s,n){const r=this.sanitizePassiveHandlers(t),i=this.getUpdatedHTMLContent(e,s,n),a=(new DOMParser).parseFromString(r,"text/html");i&&a.body.insertAdjacentElement("afterbegin",i),this.updateBodyContent(a.body.outerHTML)}getUpdatedHTMLContent(e,t,s){const n=document.createElement("div");if(n.id="afterbegin-8D95D",s&&t?.success){const t=e.replace(s,"");n.innerHTML=t}else n.innerHTML=e;return n.innerHTML?n:null}async updateBodyContent(e){const t=this.saveScrollPositions();this.saveElementState();const s=(new DOMParser).parseFromString(e,"text/html");await this.appendCallbackResponse(s),this.restoreElementState(),this.restoreScrollPositions(t),await this.processInlineModuleScripts(),await this.initMakeReactive()}restoreElementState(){if(this._elementState.focusId){const e=document.getElementById(this._elementState.focusId)||document.querySelector(`[name="${this._elementState.focusId}"]`);if(e instanceof HTMLInputElement){const t=e.value.length||0;void 0!==this._elementState.focusSelectionStart&&null!==this._elementState.focusSelectionEnd&&e.setSelectionRange(t,t),this._elementState.focusValue&&("checkbox"===e.type||"radio"===e.type?e.checked=!!this._elementState.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._elementState.focusValue)),e.focus()}else if(e instanceof HTMLTextAreaElement){const t=e.value.length||0;void 0!==this._elementState.focusSelectionStart&&null!==this._elementState.focusSelectionEnd&&e.setSelectionRange(t,t),this._elementState.focusValue&&""!==e.value&&(e.value=this._elementState.focusValue),e.focus()}else e instanceof HTMLSelectElement&&(this._elementState.focusValue&&""!==e.value&&(e.value=this._elementState.focusValue),e.focus())}this._elementState.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)}saveElementState(){const e=document.activeElement;this._elementState.focusId=e?.id||e?.name,this._elementState.focusValue=e?.value,this._elementState.focusChecked=e?.checked,this._elementState.focusType=e?.type,this._elementState.focusSelectionStart=e?.selectionStart,this._elementState.focusSelectionEnd=e?.selectionEnd,this._elementState.isSuspense=e.hasAttribute("pp-suspense"),this._elementState.checkedElements.clear(),document.querySelectorAll('input[type="checkbox"]:checked').forEach((e=>{this._elementState.checkedElements.add(e.id||e.name)})),document.querySelectorAll('input[type="radio"]:checked').forEach((e=>{this._elementState.checkedElements.add(e.id||e.name)}))}updateElementAttributes(e,t){for(const s in t)if(t.hasOwnProperty(s))switch(s){case"innerHTML":case"outerHTML":case"textContent":case"innerText":e[s]=this.decodeHTML(t[s]);break;case"insertAdjacentHTML":e.insertAdjacentHTML(t.position||"beforeend",this.decodeHTML(t[s].html));break;case"insertAdjacentText":e.insertAdjacentText(t.position||"beforeend",this.decodeHTML(t[s].text));break;case"setAttribute":e.setAttribute(t.attrName,this.decodeHTML(t[s]));break;case"removeAttribute":e.removeAttribute(t[s]);break;case"className":e.className=this.decodeHTML(t[s]);break;case"classList.add":e.classList.add(...this.decodeHTML(t[s]).split(","));break;case"classList.remove":e.classList.remove(...this.decodeHTML(t[s]).split(","));break;case"classList.toggle":e.classList.toggle(this.decodeHTML(t[s]));break;case"classList.replace":const[n,r]=this.decodeHTML(t[s]).split(",");e.classList.replace(n,r);break;case"dataset":e.dataset[t.attrName]=this.decodeHTML(t[s]);break;case"style":Object.assign(e.style,t[s]);break;case"value":e.value=this.decodeHTML(t[s]);break;case"checked":e.checked=t[s];break;default:e.setAttribute(s,this.decodeHTML(t[s]))}}decodeHTML(e){const t=document.createElement("textarea");return t.innerHTML=e,t.value}appendAfterbegin(e){if(!e)return;const t="afterbegin-8D95D";let s=document.getElementById(t);s?(s.innerHTML=e,document.body.insertAdjacentElement("afterbegin",s)):(s=document.createElement("div"),s.id=t,s.innerHTML=e,document.body.insertAdjacentElement("afterbegin",s))}restoreSuspenseElement(e){const t=e.getAttribute("pp-original-state");if(e.hasAttribute("pp-suspense")&&t){const s=(e,t)=>{for(const s in t)t.hasOwnProperty(s)&&("textContent"===s?e.textContent=t[s]:"innerHTML"===s?e.innerHTML=t[s]:"disabled"===s?!0===t[s]?e.setAttribute("disabled","true"):e.removeAttribute("disabled"):e.setAttribute(s,t[s]));for(const s of Array.from(e.attributes))t.hasOwnProperty(s.name)||e.removeAttribute(s.name)},n=(e,t)=>{for(const n in t)if(t.hasOwnProperty(n))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 n=this.parseJson(e);s(t,n)}else r(t,e);t.removeAttribute("pp-original-state")}}},r=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},i=(e,t)=>{e instanceof HTMLFormElement?n(e,t):s(e,t)};try{const r=this.parseJson(t);if(r)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 n=this.parseJson(t);s(e,n)}}}const r=new FormData(e),i={};if(r.forEach(((e,t)=>{i[t]=e})),n(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(r.targets){r.targets.forEach((e=>{const{id:t,...s}=e,n=document.querySelector(t);n&&i(n,s)}));const{targets:t,...n}=r;s(e,n)}else{const{empty:t,...n}=r;s(e,n)}}catch(e){console.error(`Error parsing JSON: ${e instanceof Error?e.message:"Unknown error"}. Please ensure the JSON string is valid.`,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,s,n={}){const r=new FormData,i=s.files;if(i)for(let e=0;e<i.length;e++)r.append("file[]",i[e]);r.append("callback",t);for(const e in n)n.hasOwnProperty(e)&&r.append(e,n[e]);const a=await this.fetch(e,{method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:r});return await a.text()}async handleSuspenseElement(e){let t=e.getAttribute("pp-suspense")||"";const s=(e,t)=>{for(const s in t)if(t.hasOwnProperty(s))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 s=this.parseJson(e);"disabled"!==s.onsubmit&&this.updateElementAttributes(t,s),s.targets&&s.targets.forEach((e=>{const{id:t,...s}=e,n=document.querySelector(t);n&&r(n,s)}))}else n(t,e)}},n=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},r=(e,t)=>{e instanceof HTMLFormElement?s(e,t):this.updateElementAttributes(e,t)};try{if(t&&this.isJsonLike(t)){const n=this.parseJson(t);if(n)if(e instanceof HTMLFormElement){const t=new FormData(e),r={};t.forEach(((e,t)=>{r[t]=e})),n.disabled&&this.toggleFormElements(e,!0);const{disabled:i,...a}=n;this.updateElementAttributes(e,a),s(e,r)}else if(n.targets){n.targets.forEach((e=>{const{id:t,...s}=e,n=document.querySelector(t);n&&r(n,s)}));const{targets:t,...s}=n;this.updateElementAttributes(e,s)}else{if("disabled"===n.empty&&""===e.value)return;const{empty:t,...s}=n;this.updateElementAttributes(e,s)}}else if(t)n(e,t);else if(e instanceof HTMLFormElement){const t=new FormData(e),n={};t.forEach(((e,t)=>{n[t]=e})),s(e,n)}}catch(e){console.error(`Error parsing JSON: ${e instanceof Error?e.message:"Unknown error"}. Please ensure the JSON string is valid.`,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 s=0;s<e.attributes.length;s++){const n=e.attributes[s];t[n.name]=n.value}e.setAttribute("pp-original-state",JSON.stringify(t))}if(e instanceof HTMLFormElement){let t=null;const s=e.id;s&&(t=document.querySelector(`[form="${s}"]`)),s&&t||(t=Array.from(e.elements).find((e=>e instanceof HTMLButtonElement||e instanceof HTMLInputElement))),t?t.hasAttribute("pp-original-state")||this.saveElementOriginalState(t):console.warn("Warning: No invoker detected for the form. Ensure the form has an associated invoker or an ID for proper handling.")}e.querySelectorAll("[pp-suspense]").forEach((e=>this.saveElementOriginalState(e)))}getUrlParams(){const e={};return new URLSearchParams(window.location.search).forEach(((t,s)=>{e[s]=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 s={};const n=e.closest("form");if(n){new FormData(n).forEach(((e,t)=>{s[t]?Array.isArray(s[t])?s[t].push(e):s[t]=[s[t],e]:s[t]=e}))}else e instanceof HTMLInputElement?s=this.handleInputElement(e):(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(s[e.name]=e.value);const r=t.match(/^(\w+)\(([\s\S]*)\)$/);if(r){const e=r[1];let t=r[2].trim();if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))if(this.isJsonLike(t))try{const e=this.parseJson(t);Array.isArray(e)?s.args=e:e&&"object"==typeof e&&(s={...s,...e})}catch(e){console.error("Error parsing JSON args:",e),s.rawArgs=t}else try{const e=this.evaluateJavaScriptObject(t);Array.isArray(e)?s.args=e:e&&"object"==typeof e?s={...s,...e}:s.rawArgs=t}catch(e){console.error("Error evaluating JS object args:",e),s.rawArgs=t}else try{const e=this.getOrCreateEvaluator(t)(this.props);s.args=[e]}catch{s.args=t.split(/,(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/).map((e=>e.trim().replace(/^['"]|['"]$/g,"")))}return{funcName:e,data:s}}return{funcName:t,data:s}}evaluateJavaScriptObject(e){try{const t=this.getOrCreateProxy(this.props);return new Function("proxy","Date","Math","JSON",`\n with (proxy) {\n return ${e};\n }\n `).call(null,t,Date,Math,JSON)}catch(e){throw console.error("Failed to evaluate JavaScript object:",e),e}}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 s=document.querySelector(`input[name="${e.name}"]:checked`);t[e.name]=s?s.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}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 s=parseInt(t.length,10)||0;e.setSelectionRange(s,s)}}handleInputAppendParams(e,t){const s=e.getAttribute("pp-append-params"),n=e.getAttribute("pp-append-params-sync");if("true"===s){if("true"===n){const t=e.name||e.id;if(t){const s=new URL(window.location.href),n=new URLSearchParams(s.search);n.has(t)&&(e.value=n.get(t)||"")}}e.addEventListener(t,(e=>{const t=e.currentTarget,s=t.value,n=new URL(window.location.href),r=new URLSearchParams(n.search),i=t.name||t.id;if(i){s?r.set(i,s):r.delete(i);const e=r.toString()?`${n.pathname}?${r.toString()}`:n.pathname;history.replaceState(null,"",e)}}))}}handleHiddenAttribute(){const e=document.querySelectorAll("[pp-visibility]"),t=document.querySelectorAll("[pp-display]"),s=this.handleElementVisibility.bind(this),n=this.handleElementDisplay.bind(this);e.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-visibility",s))),t.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-display",n)))}handleVisibilityElementAttribute(e,t,s){const n=e.getAttribute(t);if(n)if(this.isJsonLike(n)){s(e,this.parseJson(n))}else{const s=this.parseTime(n);if(s>0){const n="pp-visibility"===t?"visibility":"display",r="visibility"===n?"hidden":"none";this.scheduleChange(e,s,n,r)}}}handleElementVisibility(e,t){this.handleElementChange(e,t,"visibility","hidden","visible")}handleElementDisplay(e,t){this.handleElementChange(e,t,"display","none","block")}handleElementChange(e,t,s,n,r){const i=t.start?this.parseTime(t.start):0,a=t.end?this.parseTime(t.end):0;i>0?(e.style[s]=n,this.scheduleChange(e,i,s,r),a>0&&this.scheduleChange(e,i+a,s,n)):a>0&&this.scheduleChange(e,a,s,n)}handleAnchorTag(){document.querySelectorAll("a").forEach((e=>{e.addEventListener("click",(async e=>{const t=e.currentTarget,s=t.getAttribute("href"),n=t.getAttribute("target");if(s&&"_blank"!==n&&!e.metaKey&&!e.ctrlKey&&(e.preventDefault(),!this._isNavigating)){this._isNavigating=!0;try{if(/^(https?:)?\/\//i.test(s)&&!s.startsWith(window.location.origin))window.location.href=s;else{const e=t.getAttribute("pp-append-params");if(s.startsWith("?")&&"true"===e){const e=new URL(window.location.href),t=new URLSearchParams(e.search);let n="";const[r,i]=s.split("#");i&&(n=`#${i}`);new URLSearchParams(r.split("?")[1]).forEach(((e,s)=>{t.set(s,e)}));const a=`${e.pathname}?${t.toString()}${n}`;history.pushState(null,"",a)}else{const[e,t]=s.split("#"),n=`${e}${t?`#${t}`:""}`;history.pushState(null,"",n)}const n=s.indexOf("#");if(-1!==n){const e=s.slice(n+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){console.error("Anchor click error:",e)}finally{this._isNavigating=!1}}}))}))}handlePopState(){window.addEventListener("popstate",(async()=>{await this.handleNavigation()}))}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 void console.error(`Navigation error: ${t.status} ${t.statusText}`);const s=await t.text(),n=s.match(this._redirectRegex);if(n&&n[1])return void await this.redirect(n[1]);await this.updateDocumentContent(s)}catch(e){console.error("Navigation error:",e)}}findLoadingElement(e,t){let s=t;for(;;){const t=e.querySelector(`div[pp-loading-url='${s}']`);if(t)return t;if("/"===s)break;const n=s.lastIndexOf("/");s=n<=0?"/":s.substring(0,n)}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:s,fadeOut:n}=this.parseTransition(e);await this.fadeOut(t,n),t.innerHTML=e.innerHTML,this.fadeIn(t,s)}parseTransition(e){let t=250,s=250;const n=e.querySelector("[pp-loading-transition]"),r=n?.getAttribute("pp-loading-transition");if(r){const e=this.parseJson(r);e&&"object"==typeof e?(t=this.parseTime(e.fadeIn??t),s=this.parseTime(e.fadeOut??s)):console.warn("pp-loading-transition is not valid JSON → default values (250 ms) will be used. String:",r)}return{fadeIn:t,fadeOut:s}}fadeOut(e,t){return new Promise((s=>{e.style.transition=`opacity ${t}ms ease-out`,e.style.opacity="0",setTimeout((()=>{e.style.transition="",s()}),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(),s=this.sanitizePassiveHandlers(e),n=(new DOMParser).parseFromString(s,"text/html"),r="pp-dynamic-script",i="pp-dynamic-link";document.head.querySelectorAll("[pp-dynamic-meta]").forEach((e=>e.remove()));document.head.querySelectorAll(`[${i}]`).forEach((e=>e.remove()));document.head.querySelectorAll(`[${r}]`).forEach((e=>e.remove()));await(async e=>{Array.from(e.head.children).forEach((e=>{const t=e.tagName;if("SCRIPT"===t&&e.hasAttribute(r)){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,s=e.getAttribute("property"),n=document.head.querySelector(t?`meta[name="${t}"]`:`meta[property="${s}"]`),r=document.head.querySelector("title");n?document.head.replaceChild(e.cloneNode(!0),n):r?.nextSibling?document.head.insertBefore(e.cloneNode(!0),r.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 s=document.head.querySelector('link[rel="icon"]');if(s)document.head.replaceChild(e.cloneNode(!0),s);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.updateDocumentBody(e)})(n),this.restoreScrollPositions(t),this.resetProps(),await this.processInlineModuleScripts(),await this.initMakeReactive(),this.handlerAutofocusAttribute()}restoreScrollPositions(e){requestAnimationFrame((()=>{const t=e.window;t&&window.scrollTo(t.scrollLeft,t.scrollTop),document.querySelectorAll("*").forEach((t=>{const s=this.getElementKey(t);e[s]&&(t.scrollTop=e[s].scrollTop,t.scrollLeft=e[s].scrollLeft)}))}))}PRESERVE_HANDLERS={DETAILS:(e,t)=>(t.open=e.open,!0),INPUT(e,t){const s=e,n=t;return s.value!==n.value&&(n.value=s.value),n.checked=s.checked,document.activeElement!==s||(null!=s.selectionStart&&(n.selectionStart=s.selectionStart,n.selectionEnd=s.selectionEnd),!1)},TEXTAREA(e,t){const s=e,n=t;return s.value!==n.value&&(n.value=s.value),document.activeElement!==s||(n.selectionStart=s.selectionStart,n.selectionEnd=s.selectionEnd,!1)},SELECT(e,t){const s=e;return t.selectedIndex=s.selectedIndex,document.activeElement!==s},VIDEO(e,t){const s=e,n=t;return n.currentTime=s.currentTime,s.paused?n.pause():n.play(),!0},AUDIO:(e,t)=>this.PRESERVE_HANDLERS.VIDEO(e,t),CANVAS:()=>!1};async populateDocumentBody(e){try{const t=document.body,s=e.body;this._wheelHandlersStashed||(document.querySelectorAll("[onwheel]").forEach((e=>{const t=e.getAttribute("onwheel").trim();if(e.removeAttribute("onwheel"),t){const s=new Function("event",t);e.addEventListener("wheel",s,{passive:!0})}})),this._wheelHandlersStashed=!0);const n=this.PRESERVE_HANDLERS;morphdom(t,s,{getNodeKey(e){if(e.nodeType!==Node.ELEMENT_NODE)return;const t=e;return t.hasAttribute("pp-sync-script")?`pp-sync-script:${t.getAttribute("pp-sync-script")}`:t.getAttribute("key")||void 0},onBeforeElUpdated(e,t){const s=e.tagName;if("SCRIPT"===s||e.hasAttribute("data-nomorph"))return!1;const r=n[s];return!r||r(e,t)},onBeforeNodeDiscarded:e=>(e instanceof HTMLElement&&e.dataset.timerId&&clearTimeout(Number(e.dataset.timerId)),!0)})}catch(e){console.error("Error populating document body:",e)}}async updateDocumentBody(e){try{const t=e.body.cloneNode(!0);this.manageScriptTags(t),document.body.replaceWith(t)}catch(e){console.error("Error populating document body:",e)}}manageScriptTags(e,t){const s=e.querySelectorAll("script"),n=t?.querySelectorAll("script")||s;s.forEach(((e,t)=>{const s=document.createElement("script"),r=n[t]||e;Array.from(r.attributes).forEach((e=>{s.setAttribute(e.name,e.value)})),r.hasAttribute("src")||(s.textContent=r.textContent),e.parentNode?.replaceChild(s,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){console.error("Redirect error:",e)}}abortActiveRequest(){this._activeAbortController&&this._activeAbortController.abort()}async fetch(e,t,s=!1){let n;return s?(this._activeAbortController&&this._activeAbortController.abort(),this._activeAbortController=new AbortController,n=this._activeAbortController):n=new AbortController,fetch(e,{...t,signal:n.signal,headers:{...t?.headers,"X-Requested-With":"XMLHttpRequest"}})}isJsonLike(e){if("string"!=typeof e)return!1;const t=e.trim();return!(!/^\{[\s\S]*\}$/.test(t)&&!/^\[[\s\S]*\]$/.test(t))&&!(t.includes("(")||t.includes(")")||t.includes("=>"))}parseJson(e){try{return JSON5.parse(e)}catch(e){return console.error(`Error parsing JSON: ${e.message}. Please ensure the JSON string is valid.`,e),{}}}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":default:return e;case"s":return 1e3*e;case"m":return 60*e*1e3}}return 0}scheduleChange(e,t,s,n){setTimeout((()=>{requestAnimationFrame((()=>{e.style[s]=n}))}),t)}async fetchFunction(e,t={},s=!1){try{const n={callback:e,...t},r=window.location.href;let i;if(Object.keys(n).some((e=>{const t=n[e];return t instanceof File||t instanceof FileList&&t.length>0}))){const e=new FormData;Object.keys(n).forEach((t=>{const s=n[t];s instanceof File?e.append(t,s):s instanceof FileList?Array.from(s).forEach((s=>e.append(t,s))):e.append(t,s)})),i={method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:e}}else i=this.createFetchOptions(n);const a=await this.fetch(r,i,s);if(!a.ok)throw new Error(`Fetch failed with status: ${a.status} ${a.statusText}`);const o=await a.text();try{return JSON.parse(o)}catch{return o}}catch(e){throw console.error("Error in fetchFunction:",e),new Error("Failed to fetch data.")}}processSyncScripts(e){e.forEach((e=>{const t=`script[pp-sync-script="${CSS.escape(e)}"]`,s=document.querySelector(t);if(s){s.remove();const e=document.createElement("script");Array.from(s.attributes).forEach((t=>{e.setAttribute(t.name,t.value)})),s.src?e.src=s.src:e.textContent=s.textContent,e.type=s.type||"module",document.body.appendChild(e)}}))}async sync(...e){try{const t=this.saveScrollPositions();this.saveElementState();const s=e.length>0?e.map((e=>`pp-sync="${e}"`)):['pp-sync="true"'],n=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()}),r=await this.fetch(window.location.href,n),i=await r.text(),a=(new DOMParser).parseFromString(i,"text/html"),o=new Set;s.forEach((e=>{const t=document.querySelectorAll(`[${e}]`),s=a.body.querySelectorAll(`[${e}]`);t.forEach(((e,t)=>{const n=s[t];if(n){if(n.hasAttribute("pp-sync-script")){const e=n.getAttribute("pp-sync-script")||"";e&&o.add(e)}n.querySelectorAll("[pp-sync-script]").forEach((e=>{const t=e.getAttribute("pp-sync-script")||"";t&&o.add(t)})),e.innerHTML=n.innerHTML,this.reRunScripts(e)}}))})),this.processSyncScripts(o),this.restoreElementState(),this.restoreScrollPositions(t),this.attachWireFunctionEvents()}catch(e){console.error("Error in pphpSync:",e)}}async fetchAndUpdateBodyContent(){const e=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});this.abortActiveRequest();const t=await this.fetch(window.location.href,e,!0),s=await t.text();await this.updateBodyContent(s)}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,s,n,r="img",i=2e3){if(!(e instanceof HTMLElement))return;const a=e.closest(`.${t}`)?.querySelector("pre code"),o=a?.textContent?.trim()||"";o?navigator.clipboard.writeText(o).then((()=>{const t=e.querySelector(r);if(t)for(const[e,s]of Object.entries(n))e in t?t[e]=s:t.setAttribute(e,s);setTimeout((()=>{if(t)for(const[e,n]of Object.entries(s))e in t?t[e]=n:t.setAttribute(e,n)}),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{state;static instance=null;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})}}}class SearchParamsManager{static instance=null;listeners=[];constructor(){}static getInstance(){return SearchParamsManager.instance||(SearchParamsManager.instance=new SearchParamsManager),SearchParamsManager.instance}get params(){return new URLSearchParams(window.location.search)}get(e){return this.params.get(e)}set(e,t){const s=this.params;s.set(e,t),this.updateURL(s)}delete(e){const t=this.params;t.delete(e),this.updateURL(t)}replace(e){const t=new URLSearchParams;for(const s in e){const n=e[s];null!==n&&t.set(s,n)}this.updateURL(t,!0)}updateURL(e,t=!1){const s=`${window.location.pathname}?${e.toString()}`;t?history.replaceState(null,"",s):history.pushState(null,"",s),this.notifyListeners(e)}listen(e){this.listeners.push(e)}notifyListeners(e){for(const t of this.listeners)t(e)}enablePopStateListener(){window.addEventListener("popstate",(()=>{this.notifyListeners(this.params)}))}}var pphp=PPHP.instance,store=PPHPLocalStore.getInstance(),searchParams=SearchParamsManager.getInstance();
1
+ (()=>{const e=EventTarget.prototype.addEventListener,t=EventTarget.prototype.removeEventListener,s=new Map,n=new Set(["wheel","mousewheel","touchstart","touchmove","touchend","touchcancel","scroll"]);EventTarget.prototype.addEventListener=function(t,r,i){let a=i;n.has(t)&&(void 0===a?a={passive:!0}:"boolean"==typeof a?a={capture:a,passive:!0}:a&&void 0===a.passive&&(a={...a,passive:!0})),s.has(this)||s.set(this,new Map);const o=s.get(this),c=o.get(t)||new Set;c.add(r),o.set(t,c),e.call(this,t,r,a)},EventTarget.prototype.removeEventListener=function(e,n,r){if(s.has(this)&&s.get(this).has(e)){const t=s.get(this).get(e);t.delete(n),0===t.size&&s.get(this).delete(e)}t.call(this,e,n,r)},EventTarget.prototype.removeAllEventListeners=function(e){if(!s.has(this))return;const n=s.get(this).get(e);n&&(n.forEach((s=>{t.call(this,e,s)})),s.get(this).delete(e))}})();class PPHP{props={};_isNavigating=!1;_responseData=null;_elementState={checkedElements:new Set};_activeAbortController=null;_reservedWords;_declaredStateRoots=new Set;_arrayMethodCache=new WeakMap;_scopedKeys=new Map;_updateScheduled=!1;_pendingBindings=new Set;_effects=new Set;_pendingEffects=new Set;_processedPhpSections=new Set;_processedPhpScripts=new WeakSet;_bindings=[];_templateStore=new WeakMap;_inlineDepth=0;_activeSection=null;_inlineModuleFns=new Map;_proxyCache=new WeakMap;_rawProps={};_refs=new Map;_wheelHandlersStashed=!1;_evaluatorCache=new Map;_depsCache=new Map;_dirtyDeps=new Set;_handlerCache=new Map;_handlerProxyCache=new WeakMap;_sharedStateMap=new Map;_sectionParentMap=new Map;_sectionRefs=new Map;_processedLoops=new WeakSet;_eventHandlers;_redirectRegex=/redirect_7F834\s*=\s*(\/[^\s]*)/;_assignmentRe=/^\s*[\w.]+\s*=(?!=)/;_mustacheRe=/\{\{\s*([\s\S]+?)\s*\}\}/gu;_mutators;_boolAttrs=new Set(["allowfullscreen","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","itemscope","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected","truespeed"]);static _instance;static _effectCleanups;static _debounceTimers=new Map;static _shared=new Map;static _cryptoKey=null;static _lastJWT=null;static _cancelableEvents=new Set(["click","submit","change"]);static _mustacheTest=/\{\{\s*[\s\S]+?\s*\}\}/;static _mustachePattern=/\{\{\s*([\s\S]+?)\s*\}\}/g;static _passiveEvents=new Set(["wheel","mousewheel","touchstart","touchmove","touchend","touchcancel","scroll"]);static _bareCallRe=/^[A-Za-z_$]\w*\s*\(.*\)$/;static _autoPrefixes=new Set;constructor(){const e=Object.getOwnPropertyNames(HTMLElement.prototype).filter((e=>e.startsWith("on"))),t=Object.getOwnPropertyNames(Document.prototype).filter((e=>e.startsWith("on"))),s=Object.getOwnPropertyNames(Window.prototype).filter((e=>e.startsWith("on")));this._eventHandlers=new Set([...e,...t,...s].map((e=>e.toLowerCase()))),this._reservedWords=new Set(["null","undefined","true","false","await","break","case","catch","class","const","continue","debugger","default","delete","do","else","export","extends","finally","for","function","if","import","in","instanceof","let","new","return","super","switch","this","throw","try","typeof","var","void","while","with","yield","async","await","implements","interface","event","NaN","Infinity","Number","String","Boolean","Object","Array","Function","Date","RegExp","Error","JSON","Math","Map","Set"]),this._mutators=new Set(["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"]),this.handlePopState(),this._proxyCache=new WeakMap,this._evaluatorCache.clear(),this._depsCache.clear(),this.props=this.makeReactive(this._rawProps),this.scheduleInitialHydration()}static get instance(){return PPHP._instance||(PPHP._instance=new PPHP),PPHP._instance}scheduleInitialHydration(){const e=()=>new Promise((e=>setTimeout(e,0))),t=async()=>{await Promise.all([this.initRefs(),this.processInlineModuleScripts()]),await e(),await this.initializeAllReferencedProps(),await e(),await this.initBindings(),await e(),await this.initLoopBindings(),await e(),await this.attachWireFunctionEvents();for(let t=0;t<this._bindings.length;t+=250)this._bindings.slice(t,t+250).forEach((e=>e.update())),await e();document.body.removeAttribute("hidden")};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t,{once:!0}):t()}async initCryptoKey(){const e=document.cookie.split("; ").find((e=>e.startsWith("pphp_function_call_key=")));if(!e)throw new Error("Missing HMAC-secret cookie");const t=e.split("=",2)[1],s=document.cookie.split("; ").find((e=>e.startsWith("pphp_function_call_jwt=")));if(!s)throw new Error("Missing JWT cookie");const n=s.split("=",2)[1];if(n===PPHP._lastJWT&&PPHP._cryptoKey)return;PPHP._lastJWT=n,PPHP._cryptoKey=null;const[r,i,a]=n.split(".");if(!r||!i||!a)throw new Error("Malformed JWT");const o=await crypto.subtle.importKey("raw",(new TextEncoder).encode(t),{name:"HMAC",hash:"SHA-256"},!1,["verify"]),c=(new TextEncoder).encode(`${r}.${i}`),l=Uint8Array.from(atob(a.replace(/-/g,"+").replace(/_/g,"/")),(e=>e.charCodeAt(0)));if(!await crypto.subtle.verify("HMAC",o,l,c))throw new Error("Invalid session key signature");const h=atob(i.replace(/-/g,"+").replace(/_/g,"/")),p=JSON.parse(h);if("string"!=typeof p.k)throw new Error("Missing AES key in token");const d=Uint8Array.from(atob(p.k),(e=>e.charCodeAt(0)));if(32!==d.byteLength)throw new Error("Bad key length");PPHP._cryptoKey=await crypto.subtle.importKey("raw",d,{name:"AES-CBC"},!1,["encrypt","decrypt"])}async encryptCallbackName(e){await this.initCryptoKey();const t=crypto.getRandomValues(new Uint8Array(16)),s=(new TextEncoder).encode(e),n=await crypto.subtle.encrypt({name:"AES-CBC",iv:t},PPHP._cryptoKey,s);return`${btoa(String.fromCharCode(...t))}:${btoa(String.fromCharCode(...new Uint8Array(n)))}`}async decryptCallbackName(e){await this.initCryptoKey();const[t,s]=e.split(":",2),n=Uint8Array.from(atob(t),(e=>e.charCodeAt(0))),r=Uint8Array.from(atob(s),(e=>e.charCodeAt(0))).buffer,i=await crypto.subtle.decrypt({name:"AES-CBC",iv:n},PPHP._cryptoKey,r);return(new TextDecoder).decode(i)}qsa(e,t){return e.querySelectorAll(t)}getScopeId(e){for(;e;){const t=e.getAttribute("pp-phpx-id");if(t)return t;const s=e.getAttribute("pp-section-id");if(s)return s;e=e.parentElement}return null}getSectionId(e){for(;e;){const t=e.getAttribute("pp-section-id");if(t)return t;e=e.parentElement}return null}getPhpxId(e){for(;e;){const t=e.getAttribute("pp-phpx-id");if(t)return t;e=e.parentElement}return null}getPhpxParentId(e){if(!e)return null;let t=e,s=null;for(;t&&!s;)s=t.getAttribute("pp-phpx-id"),s||(t=t.parentElement);let n=t?.parentElement;for(;n;){const e=n.getAttribute("pp-phpx-id");if(e&&e!==s)return e;n=n.parentElement}return null}ref(e,t){const s=this._activeSection;let n=[];if(s&&(n=this._sectionRefs.get(s)?.get(e)??[]),0===n.length&&(n=this._refs.get(e)??[]),null!=t){const s=n[t];if(!s)throw new Error(`pphp.ref('${e}', ${t}) — no element at that index`);return s}if(0===n.length)throw new Error(`pphp.ref('${e}') failed — no element was found`);return 1===n.length?n[0]:n}effect(e,t){const s=this._currentScopeId(),n=Array.isArray(t),r=n?t:[],i=n&&0===r.length,a=r.map((e=>{if("function"==typeof e&&e.__pphp_key)return e.__pphp_key;if("string"!=typeof e)return"";if(e.includes("_"))return e;for(const[t,s]of this._scopedKeys)if(s.has(e))return`${t}_${e}`;if(s){const t=this._sharedStateMap.get(s);if(t?.has(e)){const t=this._sectionParentMap.get(s);return t?`${t}_${e}`:e}}return e})).filter(Boolean),o=new Set(a),c=new Map;for(const e of a){const t=this.getNested(this.props,e);c.set(e,t)}let l=0;PPHP._effectCleanups||(PPHP._effectCleanups=new WeakMap);const h=PPHP._effectCleanups,p=()=>{const t=h.get(p);if(t){try{t()}catch(e){console.error("cleanup error:",e)}h.delete(p)}if(++l>50)throw new Error("PPHP: effect ran >50 times — possible loop");if(!i&&a.length>0){let e=!1;for(const t of a){if(this.getNested(this.props,t)!==c.get(t)){e=!0;break}}if(!e)return;for(const e of a)c.set(e,this.getNested(this.props,e))}try{const t=e();"function"==typeof t&&h.set(p,t)}catch(e){console.error("effect error:",e)}};Object.assign(p,{__deps:o,__sectionId:s??null,__static:i});try{const t=e();"function"==typeof t&&h.set(p,t)}catch(e){console.error("effect error (initial):",e)}for(const e of a)c.set(e,this.getNested(this.props,e));const d=n&&this._inlineDepth>0?this._pendingEffects:this._effects;return i?this._effects.add(p):d.add(p),()=>{const e=h.get(p);if(e){try{e()}catch(e){console.error("cleanup error:",e)}h.delete(p)}this._effects.delete(p),this._pendingEffects.delete(p)}}resetProps(){this._isNavigating=!1,this._activeAbortController&&this._activeAbortController.abort(),this._activeAbortController=null,this._responseData=null,Object.keys(this._rawProps).forEach((e=>{if(window.hasOwnProperty(e)){const t=Object.getOwnPropertyDescriptor(window,e);t?.configurable&&delete window[e]}})),this._rawProps={},this.clearShare(),this._proxyCache=new WeakMap,this._templateStore=new WeakMap,this._arrayMethodCache=new WeakMap,this._handlerProxyCache=new WeakMap,this._processedLoops=new WeakSet,this._depsCache.clear(),this._evaluatorCache.clear(),this._handlerCache.clear(),this._sharedStateMap.clear(),this._sectionParentMap.clear(),this._sectionRefs.clear(),this._processedPhpSections.clear(),this._processedPhpScripts=new WeakSet,this._scopedKeys.clear(),this._declaredStateRoots.clear(),this._inlineModuleFns.clear(),this._inlineDepth=0,this._activeSection=null,PPHP._autoPrefixes.clear(),this._bindings=[],this._pendingBindings.clear(),this._effects.clear(),this._pendingEffects.clear(),PPHP._effectCleanups=new WeakMap,this._refs.clear(),this._sectionRefs.clear(),PPHP._debounceTimers.forEach((e=>clearTimeout(e))),PPHP._debounceTimers.clear(),this._updateScheduled=!1,this._wheelHandlersStashed=!1,this.props=this.makeReactive(this._rawProps)}async initReactiveOn(e=document.body){const t=()=>new Promise((e=>setTimeout(e,0)));await Promise.all([this.initRefs(e),await this.processInlineModuleScripts(e)]),await t(),await this.initializeAllReferencedProps(e),await t(),await this.initBindings(e),await t(),await this.initLoopBindings(e),await t();for(let e=0;e<this._bindings.length;e+=250)this._bindings.slice(e,e+250).forEach((e=>e.update())),await t();e===document.body&&document.body.removeAttribute("hidden")}async initLoopBindings(e=document.body){this.qsa(e,"template[pp-for]").forEach((e=>{this._processedLoops.has(e)||(this._processedLoops.add(e),this.registerLoop(e))}))}registerLoop(e){const t=this.getScopeId(e),s=e.getAttribute("pp-for").trim(),[n,r]=s.split(/\s+in\s+/),[i,a]=n.replace(/^\(|\)$/g,"").split(",").map((e=>e.trim())),o=t?`${t}_${i}`:i,c=a?t?`${t}_${a}`:a:null,l=t?r.replace(/\b([A-Za-z_$]\w*)\b/g,((e,s,n,r)=>"."===r[n-1]||this._reservedWords.has(s)||s.startsWith(t+"_")||this.hasNested(this.props,s)||this._sharedStateMap.get(t)?.has(s)?e:`${t}_${s}`)):r,h=e.parentNode,p=document.createComment("pp-for");h.insertBefore(p,e),h.removeChild(e);const d=this.makeSafeEvaluator(l),u=e=>t?e.replace(new RegExp(`\\b${i}\\b`,"g"),o).replace(a?new RegExp(`\\b${a}\\b`,"g"):/$^/,c??""):e,f=this.extractDependencies(l),m=l.match(/^\s*([A-Za-z_$]\w*)\s*\(/);if(m){const e=m[1],t=this._inlineModuleFns.get(e);if("function"==typeof t){const e=t.toString();this.extractDependencies(e).forEach((e=>f.add(e.split(".")[0])))}}this._bindings.push({dependencies:f,update:()=>{const t=document.activeElement;let s=null,n=null;if((t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement)&&h.contains(t)){const e=t.closest("[key]");s=e?.getAttribute("key")??null,n=t.selectionStart}for(let e=p.nextSibling;e&&e.nodeType!==Node.COMMENT_NODE;){const t=e.nextSibling;h.removeChild(e),e=t}const r=this.getOrCreateProxy(this.props),l=d(r);Array.isArray(l)||console.warn("[pp-for] expected an Array but got:",l);if((Array.isArray(l)?l:[]).forEach(((t,s)=>{this.props[o]=t,c&&(this.props[c]=s);const n=e.content.cloneNode(!0),r=document.createTreeWalker(n,NodeFilter.SHOW_TEXT);for(let e;e=r.nextNode();)e.nodeValue=(e.nodeValue||"").replace(PPHP._mustachePattern,((e,t)=>{try{const e=u(t);return this.formatValue(this.makeSafeEvaluator(e)(this.props))}catch{return""}}));n.querySelectorAll("*").forEach((e=>{for(const{name:t,value:s}of Array.from(e.attributes)){if("pp-bind"===t){const t=u(s),n=this.makeSafeEvaluator(t)(this.props);e.textContent=this.formatValue(n);continue}if("pp-bind-expr"===t){const t=this.decodeEntities?this.decodeEntities(s):s,n=u(t),r=this.makeSafeEvaluator(n)(this.props);e.textContent=this.formatValue(r);continue}const n=t.match(/^pp-bind-(.+)$/);if(!n)continue;const r=n[1],i=u(s),a=this.makeSafeEvaluator(i)(this.props);if(this._boolAttrs.has(r)){const t=!!a;e[r]=t,t?e.setAttribute(r,""):e.removeAttribute(r)}else r in e?e[r]=a:e.setAttribute(r,String(a))}})),n.querySelectorAll("*").forEach((e=>{for(const{name:t,value:s}of Array.from(e.attributes)){const n=t.match(/^pp-bind-(.+)$/);if(!n)continue;const r=n[1],i=u(s),a=this.makeSafeEvaluator(i)(this.props);if(this._boolAttrs.has(r)){const t=!!a;e[r]=t,t?e.setAttribute(r,""):e.removeAttribute(r)}else r in e?e[r]=a:e.setAttribute(r,String(a))}})),n.querySelectorAll("*").forEach((e=>{Array.from(e.attributes).forEach((n=>{const r=n.name.startsWith("on"),o=n.name.startsWith("pp-inc-on"),c=n.name.startsWith("pp-comp-on");if(!r&&!o&&!c)return;let l=n.value;/\b(?:i|idx)\b/.test(l)&&(l=((e,t)=>e.replace(/\[\s*(?:i|idx)\s*\]/g,`[${t}]`).replace(/(^|[^\w$])(?:i|idx)(?!\w)/g,((e,s)=>s+t)))(l,s));const h=new RegExp(`\\b${i}\\b`,"g");var p;if(l=l.replace(h,(p=t,JSON.stringify(p))),a){const e=new RegExp(`\\b${a}\\b`,"g");l=l.replace(e,String(s))}e.setAttribute(n.name,l)}))})),h.insertBefore(n,p.nextSibling)})),null!==s){const e=h.querySelector(`[key="${s}"]`),t=e?.querySelector("input,textarea");if((t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement)&&(t.focus({preventScroll:!0}),null!==n)){const e=Math.min(n,t.value.length);t.setSelectionRange(e,e)}}this.attachWireFunctionEvents()}})}async initRefs(e=document.body){this.qsa(e,"[pp-ref]").forEach((e=>{const t=e.getAttribute("pp-ref"),s=this.getScopeId(e)??"__global__",n=this._sectionRefs.get(s)??new Map,r=n.get(t)??[];r.push(e),n.set(t,r),this._sectionRefs.set(s,n);const i=this._refs.get(t)??[];i.push(e),this._refs.set(t,i),e.removeAttribute("pp-ref")}))}scheduleBindingUpdate(e){this._pendingBindings.add(e),this._updateScheduled||(this._updateScheduled=!0,requestAnimationFrame((()=>{this.flushBindings()})))}makeReactive(e,t=[]){const s=this._proxyCache.get(e);if(s)return s;if(e instanceof Map||e instanceof Set||"object"!=typeof e||null===e)return e;const n=this,r=new Proxy(e,{get(e,s,r){const i=Reflect.get(e,s,r);if(Array.isArray(e)&&"string"==typeof s&&n._mutators.has(s)){let a=n._arrayMethodCache.get(e);if(a||(a=new Map,n._arrayMethodCache.set(e,a)),!a.has(s)){const e=i.bind(r),o=t.join("."),c=function(...t){const s=e(...t);return queueMicrotask((()=>{n._bindings.forEach((e=>{e.dependencies.has(o)&&n.scheduleBindingUpdate(e)}))})),s};a.set(s,c)}return a.get(s)}return null!==i&&"object"==typeof i?n.makeReactive(i,[...t,s]):i},set(e,s,r,i){let a=r;null!==r&&"object"==typeof r&&(a=n.makeReactive(r,[...t,s]));const o=e[s],c=Reflect.set(e,s,a,i);if(o===a)return c;const l=[...t,s].join(".");return n._bindings.forEach((e=>{for(const t of e.dependencies)if(l===t||l.startsWith(t+".")||t.startsWith(l+".")){n.scheduleBindingUpdate(e);break}})),c}});return this._proxyCache.set(e,r),r}makeAttrTemplateUpdater(e,t,s,n){let r=this._templateStore.get(e);r||(r=new Map,this._templateStore.set(e,r)),r.has(t)||r.set(t,e.getAttribute(t)||"");const i=n??r.get(t)??"",a=this.getScopeId(e),o=a&&this._scopedKeys.get(a)||new Set,c=a&&this._sharedStateMap.get(a)||new Set,l=a?this._sectionParentMap.get(a)??null:null,h=e=>a?e.replace(/\b([A-Za-z_$][\w$]*)\b/g,((e,t,s,n)=>{if("."===n[s-1]||this._reservedWords.has(t))return e;if(c.has(t))return l?`${l}_${t}`:t;if(o.has(t)||this._declaredStateRoots.has(`${a}_${t}`))return`${a}_${t}`;let r=this._sectionParentMap.get(a)||null;for(;r;){if(this._scopedKeys.get(r)?.has(t)||this.hasNested(this.props,`${r}_${t}`))return`${r}_${t}`;r=this._sectionParentMap.get(r)||null}return e})):e;return(i.match(this._mustacheRe)||[]).forEach((e=>{const t=e.replace(/^\{\{\s*|\s*\}\}$/g,"");this.extractDependencies(h(t)).forEach((e=>s.add(e)))})),()=>{try{const s=i.replace(this._mustacheRe,((e,t)=>{try{const e=h(t),s=this.makeSafeEvaluator(e);return this.formatValue(s(this.props))}catch(e){return console.error("Error token:",t,e),""}}));e.getAttribute(t)!==s&&e.setAttribute(t,s)}catch(e){console.error(`Error evaluating the template for attribute "${t}". Please check the template syntax and dependencies.`,e)}}}makePrimitiveUpdater(e,t,s){const n={};return this._eventHandlers.forEach((e=>{if(e.startsWith("on")){const t=e.slice(2);n[t]=t}})),n.value="input",n.checked="change",()=>{try{const r=s(this.props),i=this.formatValue(r);let a=!1;if("value"===t){const t=e;"value"in e&&t.value!==i?(t.value=i,a=!0):"value"in e||(e.setAttribute("value",i),a=!0)}else{const t=e,s="true"===i;"checked"in e&&t.checked!==s?(t.checked=s,a=!0):"checked"in e||(e.setAttribute("checked",i),a=!0)}if(!a||e instanceof HTMLInputElement&&("hidden"===e.type||e.disabled||e.readOnly))return;const o=n[t]||t,c="click"===o?new MouseEvent(o,{bubbles:!0,cancelable:!0}):new Event(o,{bubbles:!0});e.dispatchEvent(c)}catch(e){console.error(`Error evaluating attribute "${t}":`,e)}}}formatValue(e){return null!==e&&"object"==typeof e&&1===Object.keys(e).length&&Object.prototype.hasOwnProperty.call(e,"value")?this.formatValue(e.value):"function"==typeof e?"":"boolean"==typeof e?e?"true":"false":Array.isArray(e)?e.map((e=>"object"==typeof e?JSON.stringify(e):String(e))).join(", "):e&&"object"==typeof e?Object.keys(e).length?JSON.stringify(e,null,2):"":e?.toString()??""}registerBinding(e,t,s="text",n){if(this._assignmentRe.test(t))return;const r=this.getScopeId(e);let i=t;if(r){const e=this._scopedKeys.get(r)||new Set,s=this._sharedStateMap.get(r)||new Set,n=this._sectionParentMap.get(r);i=t.replace(/\b([A-Za-z_$][\w$]*)\b/g,((t,i,a,o)=>{if("."===o[a-1]||this._reservedWords.has(i))return t;if(s.has(i))return n?`${n}_${i}`:i;if(e.has(i)||this._declaredStateRoots.has(`${r}_${i}`))return`${r}_${i}`;let c=this._sectionParentMap.get(r)||null;for(;c;){if(this._scopedKeys.get(c)?.has(i)||this.hasNested(this.props,`${c}_${i}`))return`${c}_${i}`;c=this._sectionParentMap.get(c)||null}return t}))}const a=new Set([...this.extractDependencies(i)].map((e=>e.split(".")[0])).filter((e=>e in this.props&&!this._reservedWords.has(e)))),o=this.makeSafeEvaluator(i);if("value"===n||"checked"===n){const t=this.makePrimitiveUpdater(e,n,o);return void this._bindings.push({dependencies:a,update:t})}if(n){const s=n.toLowerCase();if(this._boolAttrs.has(s)){e.removeAttribute(s);const r=()=>{try{const t=!!o(this.props);e[n]!==t&&(e[n]=t),t?e.setAttribute(s,""):e.removeAttribute(s)}catch(e){console.error(`PPHP: error evaluating boolean attribute ${n}="${t}"`,e)}};return void this._bindings.push({dependencies:a,update:r})}const c=e.getAttribute(n)??"";if(this._mustacheRe.test(i)||this._mustacheRe.test(c)){const t=this._scopedKeys.get(r??"")||new Set,s=this._sharedStateMap.get(r??"")||new Set,i=this._sectionParentMap.get(r??"")||null,o=c.replace(this._mustacheRe,((e,n)=>`{{ ${n.replace(/\b([A-Za-z_$][\w$]*)\b/g,((e,n,a,o)=>{if("."===o[a-1]||this._reservedWords.has(n))return e;if(s.has(n))return i?`${i}_${n}`:n;if(t.has(n)||this._declaredStateRoots.has(`${r}_${n}`))return`${r}_${n}`;let c=this._sectionParentMap.get(r??"")||null;for(;c;){if(this._scopedKeys.get(c)?.has(n)||this.hasNested(this.props,`${c}_${n}`))return`${c}_${n}`;c=this._sectionParentMap.get(c)||null}return e}))} }}`)),l=this.makeAttrTemplateUpdater(e,n,a,o);return void this._bindings.push({dependencies:a,update:l})}const l=()=>{try{const t=o(this.props),s=this.formatValue(t);n in e&&(e[n]=s),e.setAttribute(n,s)}catch(e){console.error(`Error evaluating attribute ${n}="${t}"`,e)}};return void this._bindings.push({dependencies:a,update:l})}const c={text(e,t){e.textContent!==t&&(e.textContent=t)},value(e,t){e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement?e.value!==t&&(e.value=t):e.setAttribute("value",t)},checked(e,t){e instanceof HTMLInputElement?e.checked="true"===t:e.setAttribute("checked",t)},attr(e,t){e.setAttribute("attr",t)}};this._bindings.push({dependencies:a,update:()=>{try{const t=o(this.props),n=this.formatValue(t);c[s](e,n)}catch(e){console.error(`Error evaluating expression "${t}"`,e)}}})}makeSafeEvaluator(e){const t=e.trim(),s=`\n try {\n with (ctx) {\n ${/^\s*[\w.]+\s*=(?!=)/.test(t)?`${t}; return "";`:`return (${t});`}\n }\n } catch {\n return "";\n }\n `;let n;try{n=new Function("ctx",s)}catch(t){const s=JSON.stringify(e);n=new Function("ctx",`try { return ${s}; } catch { return ""; }`)}return e=>{try{const t=n(e);return null==t?"":t}catch{return""}}}async initBindings(e=document.body){this._bindings=[];const t=new WeakSet;this.qsa(e,"[pp-if]").forEach((e=>{if(t.has(e))return;const s=[];let n=e;for(;n;){if(n.hasAttribute("pp-if"))s.push({el:n,expr:n.getAttribute("pp-if")});else if(n.hasAttribute("pp-elseif"))s.push({el:n,expr:n.getAttribute("pp-elseif")});else{if(!n.hasAttribute("pp-else"))break;s.push({el:n,expr:null})}t.add(n),n=n.nextElementSibling}s.forEach((e=>{if(null!==e.expr){const t=e.expr.replace(/^{\s*|\s*}$/g,"");e.deps=this.extractDependencies(t);const s=this.makeSafeEvaluator(t);e.evaluate=()=>!!s(this.props)}}));const r=new Set;s.forEach((e=>e.deps?.forEach((e=>r.add(e)))));this._bindings.push({dependencies:r,update:()=>{let e=!1;for(const{el:t,expr:n,evaluate:r}of s)!e&&null!==n&&r()?(t.removeAttribute("hidden"),e=!0):e||null!==n?t.setAttribute("hidden",""):(t.removeAttribute("hidden"),e=!0)}})})),this.qsa(e,"*").forEach((e=>{["pp-bind","pp-bind-expr"].forEach((t=>{const s=e.getAttribute(t);s&&this.registerBinding(e,s,"text")})),Array.from(e.attributes).forEach((t=>{const s=t.name.toLowerCase(),n=t.value.trim();this._boolAttrs.has(s)&&!t.name.startsWith("pp-bind-")&&/^[A-Za-z_$][\w$]*$/.test(n)&&(e.removeAttribute(t.name),this.registerBinding(e,n,"text",s))})),Array.from(e.attributes).forEach((t=>{if(!t.name.startsWith("pp-bind-"))return;const s=t.name;if("pp-bind"===s||"pp-bind-expr"===s||"pp-bind-spread"===s)return;const n=this.decodeEntities(t.value).replace(/^{{\s*|\s*}}$/g,""),r=s.replace(/^(pp-bind-)+/,""),i="value"===r?"value":"checked"===r?"checked":"text";this.registerBinding(e,n,i,r)})),Array.from(e.attributes).forEach((t=>{if("pp-bind-spread"!==t.name)return;const s=this.decodeEntities(t.value).split(",").map((e=>e.trim())).filter(Boolean),n=new Set;s.forEach((e=>n.add(e.split(".")[0])));const r=new Set;this._bindings.push({dependencies:n,update:()=>{try{const t={};s.forEach((e=>{const s=this.getNested(this.props,e)??{};Object.assign(t,s)})),r.forEach((s=>{s in t||e.hasAttribute(s)||(e.removeAttribute(s),r.delete(s))})),Object.entries(t).forEach((([t,s])=>{if(!r.has(t)&&e.hasAttribute(t))return;if(null==s||!1===s)return void(r.has(t)&&(e.removeAttribute(t),r.delete(t)));const n="object"==typeof s?JSON.stringify(s):String(s);e.getAttribute(t)!==n&&e.setAttribute(t,n),r.add(t)}))}catch(e){console.error("pp-bind-spread error:",e)}}})}))}))}callInlineModule(e,...t){const s=this._inlineModuleFns.get(e);if(!s)throw new Error(`PPHP: no inline module named "${e}"`);return s(...t)}async processInlineModuleScripts(e=document.body){this._inlineDepth++,this._sharedStateMap.clear(),this._sectionParentMap.clear();try{const t=Array.from(this.qsa(e,'script[type="text/php"]:not([src])')).filter((e=>{const t=this.getScopeId(e);return t?!this._processedPhpSections.has(t):!this._processedPhpScripts.has(e)}));if(!t.length)return;this.qsa(e,"[pp-section-id]").forEach((e=>{const t=e.getAttribute("pp-section-id"),s=this.findParentSectionId(e);s&&this._sectionParentMap.set(t,s)})),this.qsa(e,"[pp-phpx-id]").forEach((e=>{const t=e.getAttribute("pp-phpx-id"),s=this.findParentSectionId(e);s&&this._sectionParentMap.set(t,s)}));const s=this.sortScriptsByDependency(t),n={};for(const e of s){const t=this.getScopeId(e);if(!t)continue;const s=e.textContent||"";for(const[,e]of[...s.matchAll(/export\s+const\s+([A-Za-z_$]\w*)/g),...s.matchAll(/export\s+function\s+([A-Za-z_$]\w*)/g)])n[e]=t}for(const[e,t]of Object.entries(n))this._scopedKeys.has(t)||this._scopedKeys.set(t,new Set),this._scopedKeys.get(t).add(e);for(const e of s){const t=this.getScopeId(e);let s=(e.textContent||"").trim();if(s=this.decodeEntities(s),s=this.stripComments(s),s=this.transformStateDeclarations(s,t),t){const e=this._sectionParentMap.get(t)??null,n=t+"_",r=e?e+"_":"",i=new Set;if(this._declaredStateRoots.forEach((e=>{e.startsWith(n)?i.add(e.slice(n.length)):r&&e.startsWith(r)?i.add(e.slice(r.length)):e.includes("_")||i.add(e)})),i.size){let e="";for(const a of i){const i=this.hasNested(this.props,n+a)?n+a:this.hasNested(this.props,r+a)?r+a:a,o="set"+a[0].toUpperCase()+a.slice(1),c=`${t}_${a}`,l=`${t}_${o}`;new RegExp(`\\b(?:const|let|var)\\s+\\[?\\s*${a}\\b`).test(s)||(e+=`\n const ${a} = (() => {\n const fn = () => pphp.props.${i};\n fn.__pphp_key = '${i}';\n Object.defineProperty(fn, 'value', {\n get() { return pphp.props.${i}; },\n set(v) { pphp.props.${i} = v; }\n });\n return fn;\n })();\n const ${o} = v => {\n pphp.props.${i} = typeof v === 'function'\n ? v(pphp.props.${i})\n : v;\n };\n pphp._inlineModuleFns.set('${c}', ${a});\n pphp._inlineModuleFns.set('${l}', ${o});`)}s=e+"\n"+s}}const r=this.extractSetters(s,t);if(r.length){s+="\n\n";for(const e of r){s+=`pphp._inlineModuleFns.set('${t?`${t}_${e}`:e}', ${e});\n`}}if(t){const e=this._sectionParentMap.get(t)??null,n=e?e+"_":"";s=s.replace(/(\bpphp\.state\(\s*['"])([^'"]+)(['"])/g,((e,s,r,i)=>r.startsWith(t+"_")||n&&r.startsWith(n)||!r.includes("_")?s+r+i:s+`${t}_${r}`+i))}s=s.replace(/\b([A-Za-z_$]\w*)\s*\(/g,((e,t,s,r)=>{const i=r.slice(Math.max(0,s-20),s);if(/\b(?:function|export\s+function)\s*$/.test(i.trim()))return e;const a=n[t];return a?`${a}_${t}(`:e}));const i=new Blob([s],{type:"application/javascript"}),a=URL.createObjectURL(i),o=PPHP.prototype._currentScopeId;t&&(PPHP.prototype._currentScopeId=()=>t);try{const e=await import(a);for(const[s,n]of Object.entries(e))if("function"==typeof n){const e=t?`${t}_${s}`:s;this._inlineModuleFns.set(e,n)}}catch(e){console.error("Inline module import failed:",e)}finally{PPHP.prototype._currentScopeId=o,URL.revokeObjectURL(a),t?this._processedPhpSections.add(t):this._processedPhpScripts.add(e)}}}finally{this._inlineDepth--,0===this._inlineDepth&&requestAnimationFrame((()=>{this._pendingEffects.forEach((e=>this._effects.add(e))),this._pendingEffects.clear()}))}}stripComments(e){let t="",s=0,n=!1,r="",i=!1;for(;s<e.length;){const a=e[s],o=e[s+1];if(i||"'"!==a&&'"'!==a&&"`"!==a||"\\"===e[s-1])if(n)t+=a,s++;else if(i||"/"!==a||"*"!==o)if(i)"*"===a&&"/"===o?(i=!1,s+=2):s++;else if("/"!==a||"/"!==o)t+=a,s++;else for(;s<e.length&&"\n"!==e[s];)s++;else i=!0,s+=2;else n=!n,r=n?a:"",t+=a,s++}return t}findParentSectionId(e){const t=e.parentElement?.closest("[pp-section-id]");return t?t.getAttribute("pp-section-id"):null}extractSetters(e,t){const s=[],n=/\[\s*([A-Za-z_$]\w*)\s*,\s*([A-Za-z_$]\w*)\s*\]\s*=\s*pphp\.(state|share)\(/g;let r;for(;r=n.exec(e);){const[,e,n,i]=r;"share"===i&&this.markShared(t,e),t&&this._sharedStateMap.get(t)?.has(e)||s.push(n)}return s}markShared=(e,t)=>{e&&(this._sharedStateMap.has(e)||this._sharedStateMap.set(e,new Set),this._sharedStateMap.get(e).add(t))};transformStateDeclarations(e,t){return e=(e=(e=e.replace(/(\b(?:const|let|var)\s+\[\s*)([A-Za-z_$]\w*)\s*,\s*([A-Za-z_$]\w*)\s*(\]\s*=\s*pphp\.(?:state|share)\s*\(\s*)/g,((e,s,n,r,i)=>t&&this._sharedStateMap.get(t)?.has(n)?e:`${s}${n}, ${r}${i}'${n}', `))).replace(/(\b(?:const|let|var)\s+\[\s*)([A-Za-z_$]\w*)\s*(\]\s*=\s*pphp\.(?:state|share)\s*\(\s*)/g,((e,s,n,r)=>t&&this._sharedStateMap.get(t)?.has(n)?e:`${s}${n}${r}'${n}', `))).replace(/(\b(?:const|let|var)\s+)([A-Za-z_$]\w*)(\s*=\s*pphp\.(?:state|share)\s*\(\s*)/g,((e,s,n,r)=>t&&this._sharedStateMap.get(t)?.has(n)?e:`${s}[${n}] = pphp.state('${n}', `))}sortScriptsByDependency(e){const t=new Map;for(const s of e){const e=this.getScopeId(s);t.has(e)||t.set(e,[]),t.get(e).push(s)}const s=[],n=new Set,r=e=>{if(!e)return[];const t=this._sectionParentMap.get(e);if(t)return[t];const s=this._sharedStateMap.get(e);return s&&s.size>0?[t||null]:[]},i=e=>{if(n.has(e))return;for(const t of r(e))i(t);const a=t.get(e)||[];s.push(...a),n.add(e)};i(null);for(const e of t.keys())null!==e&&i(e);return s}flushBindings(){const e=new Set(this._dirtyDeps);this._pendingBindings.forEach((t=>{t.dependencies.forEach((t=>e.add(t))),t.update()})),this._pendingBindings.clear(),this._dirtyDeps.clear(),this._updateScheduled=!1,this._effects.forEach((t=>{if(t.__static)return;const s=t.__deps||new Set;if(0===s.size||[...s].some((t=>e.has(t)))){const e=this._activeSection;this._activeSection=t.__sectionId??null;try{t()}catch(e){console.error("effect error:",e)}this._activeSection=e}}))}scheduleFlush(){this._updateScheduled||(this._updateScheduled=!0,requestAnimationFrame((()=>{this._updateScheduled=!1,this.flushBindings()})))}scopeKey(e){const t=this._currentScopeId();if(!t)return e;const s=this._sharedStateMap.get(t);if(s?.has(e)){const s=this._sectionParentMap.get(t);return s?`${s}_${e}`:e}return e.startsWith(`${t}_`)?e:`${t}_${e}`}_currentScopeId(){const e=document.currentScript;return this.getScopeId(e)}getNested(e,t){return t.split(".").reduce(((e,t)=>e?e[t]:void 0),e)}setNested(e,t,s){const n=t.split("."),r=n.pop();n.reduce(((e,t)=>e[t]??={}),e)[r]=s}hasNested(e,t){return void 0!==this.getNested(e,t)}share(e,t){const s=PPHP._shared.get(e);if(s)return[s.getter,s.setter];const[n,r]=this.state(e,t);return PPHP._shared.set(e,{getter:n,setter:r}),[n,r]}clearShare=e=>{e?PPHP._shared.delete(e):PPHP._shared.clear()};state(e,t){if("string"!=typeof e||""===e.trim())throw new Error("PPHP.state: missing or invalid key—make sure your build-time injector ran and you wrote `const [foo, setFoo] = pphp.state(0)` so it became `pphp.state('foo', 0)`.");arguments.length<2&&(t=void 0);const s=this._currentScopeId(),n=e;if(this._reservedWords.has(n))throw new Error(`'${n}' is reserved – choose another state key.`);const r=this.scopeKey(n);this._declaredStateRoots.add(r),s&&(this._scopedKeys.has(s)||this._scopedKeys.set(s,new Set),this._scopedKeys.get(s).add(n)),this.hasNested(pphp.props,r)||this.setNested(pphp.props,r,t);const i=()=>this.getNested(pphp.props,r),a=e=>{const t=i(),s="function"==typeof e?e(t):e;this.setNested(pphp.props,r,s),this._dirtyDeps.add(r.split(".")[0]),this.scheduleFlush()},o=()=>i();Object.defineProperty(o,"value",{get:()=>i(),set:e=>a(e)}),Object.defineProperties(o,{valueOf:{value:()=>i()},toString:{value:()=>String(i())}}),o.__pphp_key=r;const c=i();if(null===c||"object"!=typeof c)return[o,a];return[new Proxy(o,{apply:(e,t,s)=>Reflect.apply(e,t,s),get(e,t,s){if("value"===t)return i();if(t in e)return Reflect.get(e,t,s);return i()[t]},set(e,t,s){if("value"===t)return a(s),!0;return i()[t]=s,!0},has(e,t){if("value"===t||t in o)return!0;return t in i()}}),a]}static _isBuiltIn=(()=>{const e=new Map,t=[Object.prototype,Function.prototype,Array.prototype,String.prototype,Number.prototype,Boolean.prototype,Date.prototype,RegExp.prototype,Map.prototype,Set.prototype,WeakMap.prototype,WeakSet.prototype,Error.prototype,Promise.prototype];return s=>{const n=e.get(s);if(void 0!==n)return n;const r=s in globalThis||t.some((e=>s in e));return e.set(s,r),r}})();extractDependencies(e){const t=e.trim();if(this.isPlainText(t))return new Set;let s=e.replace(/\?\./g,".");const n=new Set,r=/(?:^|[^\w$])(?:\(\s*([^)]*?)\s*\)|([A-Za-z_$][\w$]*))\s*=>/g;for(let e;e=r.exec(s);){(e[1]??e[2]??"").split(",").map((e=>e.trim())).filter(Boolean).forEach((e=>n.add(e)))}const i=/function\s*(?:[A-Za-z_$][\w$]*\s*)?\(\s*([^)]*?)\s*\)/g;for(let e;e=i.exec(s);)e[1].split(",").map((e=>e.trim())).filter(Boolean).forEach((e=>n.add(e)));const a=e=>{let t="",s=0;for(;s<e.length;)if("`"===e[s])for(s++;s<e.length;)if("\\"===e[s])s+=2;else if("$"===e[s]&&"{"===e[s+1]){s+=2;let n=1;const r=s;for(;s<e.length&&n>0;)"{"===e[s]?n++:"}"===e[s]&&n--,s++;const i=e.slice(r,s-1);t+=a(i)+" "}else{if("`"===e[s]){s++;break}s++}else t+=e[s++];return t};s=a(s),s=s.replace(/(['"])(?:\\.|[^\\])*?\1/g,""),s=s.replace(/\/(?:\\.|[^\/\\])+\/[gimsuy]*/g,"");const o=new Set,c=/\b[A-Za-z_$]\w*(?:\.[A-Za-z_$]\w*)*\b/g;for(const t of s.match(c)??[]){const[s,...r]=t.split(".");n.has(s)||(0===r.length&&PPHP._isBuiltIn(s)&&new RegExp(`\\.${s}\\b`).test(e)||o.add(t))}return o}isPlainText(e){const t=e.trim();if(/^['"`]/.test(t))return!1;return![/[+\-*/%=<>!&|?:]/,/\.\w+/,/\[\s*\w+\s*\]/,/\(\s*[^)]*\s*\)/,/=>/,/\b(true|false|null|undefined|typeof|new|delete|void|in|of|instanceof)\b/,/\?\./,/\?\?/,/\.\.\./,/\{[^}]*\}/,/\[[^\]]*\]/].some((e=>e.test(t)))&&(!!t.includes(" ")&&(!/\w+\.\w+/.test(t)&&!/\w+\[\w+\]/.test(t)))}async initializeAllReferencedProps(e=document.body){const t=PPHP._mustachePattern,s=PPHP._mustacheTest,n=this.props,r=new Set,i=(e,t)=>{if(this.hasNested(this.props,t))return t;const s=e.getAttribute("pp-section-id"),n=this.getScopeId(e.parentElement);return s??n?`${s??n}_${t}`:t},a=(()=>{const e=new Set([...Object.getOwnPropertyNames(String.prototype),...Object.getOwnPropertyNames(Array.prototype),...Object.getOwnPropertyNames(Number.prototype),...Object.getOwnPropertyNames(Boolean.prototype),...Object.getOwnPropertyNames(Object.prototype),...Object.getOwnPropertyNames(Date.prototype),...Object.getOwnPropertyNames(RegExp.prototype)]);return t=>e.has(t)})(),o=(e,t)=>{const[s,n,...o]=t.split(".");if(this._reservedWords.has(s))return;if(PPHP._isBuiltIn(s)&&console.warn(`Path “${t}” shadows built-in “${s}”.`),n&&a(n))return void r.add(i(e,s));const c=i(e,s);r.add(n?`${c}.${[n,...o].join(".")}`:c)};for(const n of this.qsa(e,"*"))for(const{name:e,value:r}of Array.from(n.attributes))if(r){if(s.test(r))for(const e of r.matchAll(t))this.extractDependencies(e[1]).forEach((e=>o(n,e)));"pp-if"!==e&&"pp-elseif"!==e||this.extractDependencies(r).forEach((e=>o(n,e))),e.startsWith("pp-bind")&&this.extractDependencies(r).forEach((e=>o(n,e)))}const c=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,{acceptNode:e=>s.test(e.nodeValue??"")?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT});let l;for(;l=c.nextNode();){const e=l.parentElement;for(const s of l.nodeValue.matchAll(t))this.extractDependencies(s[1]).forEach((t=>o(e,t)))}const h=Array.from(r).sort(((e,t)=>t.split(".").length-e.split(".").length));for(const e of h){const t=e.split(".");let s=n;for(let e=0;e<t.length;e++){const n=t[e],r=e===t.length-1,i=t.slice(0,e+1).join(".");n in s&&(r||null!=s[n]&&"object"==typeof s[n])||r&&this._declaredStateRoots.has(i)||(s[n]=r?void 0:{}),s=s[n]}}}setNestedProperty(e,t,s){const n=t.split(".");let r=e;for(let e=0;e<n.length-1;e++)n[e]in r||(r[n[e]]={}),r=r[n[e]];r[n[n.length-1]]=s}async attachWireFunctionEvents(){this.handleHiddenAttribute(),this.handleAnchorTag();const e=e=>Array.from(this._eventHandlers).map((t=>`[${e}${t}]`)),t=[...e(""),...e("pp-inc-"),...e("data-pp-child-"),...e("data-pp-parent-")].flat().join(","),s=this.qsa(document.body,t);for(const e of s){const t=this.getSectionId(e),s=this.getPhpxId(e),n=this.getPhpxParentId(e);t&&PPHP._autoPrefixes.add(`${t}_`),s&&PPHP._autoPrefixes.add(`${s}_`),n&&PPHP._autoPrefixes.add(`${n}_`);for(const r of this._eventHandlers){const i=r,a=`pp-inc-${r}`,o=`data-pp-child-${r}`,c=`data-pp-parent-${r}`,l=e.getAttribute(i),h=e.getAttribute(a),p=e.getAttribute(o),d=e.getAttribute(c),u=l?this.decodeEntities(l).trim():"",f=h?this.decodeEntities(h).trim():"",m=p?this.decodeEntities(p).trim():"",g=d?this.decodeEntities(d).trim():"";if(!(u||f||m||g))continue;const y=[];if(u&&y.push(this.unwrapArrowBody(this.buildHandlerFromRawBody(u,null))),f&&y.push(this.unwrapArrowBody(this.buildHandlerFromRawBody(f,t))),m&&y.push(this.unwrapArrowBody(this.buildHandlerFromRawBody(m,s))),g){const e=n||t||null;y.push(this.unwrapArrowBody(this.buildHandlerFromRawBody(g,e)))}const b=`(event) => { ${[...new Set(y)].join(" ")} }`;[i,a,o,c].forEach((t=>e.removeAttribute(t)));const _=r.slice(2);e.removeAllEventListeners(_),e instanceof HTMLInputElement&&this.handleInputAppendParams(e,_),this.handleDebounce(e,_,b)}}this.handlePassiveWheelStashes(document)}prefixFunctionCalls(e,t){const s=this._scopedKeys.get(t)||new Set,n=e=>s.has(e)||this._declaredStateRoots.has(`${t}_${e}`);return e.replace(/\b([A-Za-z_$][\w$]*)\s*\(/g,((e,s)=>this._reservedWords.has(s)||s.startsWith(`${t}_`)||!n(s)?e:`${t}_${s}(`))}prefixIds(e,t,s=new Set){let n="",r=0,i=(e=this.prefixFunctionCalls(e,t)).length,a=!1,o=!1,c=!1;for(;r<i;){const l=e[r];if("'"!==l||o||c||"\\"===e[r-1])if('"'!==l||a||c||"\\"===e[r-1])if("`"!==l||a||o||"\\"===e[r-1])if(a||o||c)n+=l,r++;else if(/[A-Za-z_$]/.test(l)){let a=r+1;for(;a<i&&/[\w$]/.test(e[a]);)a++;const o=e.slice(r,a),c=e[r-1]??"",l=this._reservedWords.has(o),h="."===c;n+=!(o.startsWith(`${t}_`)||h||l||s.has(o))?`${t}_${o}`:o,r=a}else n+=l,r++;else c=!c,n+=l,r++;else o=!o,n+=l,r++;else a=!a,n+=l,r++}return n}decodeEntities=e=>{const t=document.createElement("textarea");t.innerHTML=e;let s=t.value;for(;s.includes("&");){t.innerHTML=s;const e=t.value;if(e===s)break;s=e}return s};unwrapArrowBody=e=>{if(!e.trim())return"";const t=e.match(/^\s*(?:\([\w\s,]*\)|[A-Za-z_$][\w$]*)\s*=>\s*\{([\s\S]*)\}\s*$/);if(t){let e=t[1].trim();return e&&!e.endsWith(";")&&(e+=";"),e}const s=e.match(/^\s*(?:\([\w\s,]*\)|[A-Za-z_$][\w$]*)\s*=>\s*/);if(s){let t=e.substring(s[0].length).trim();return t&&!t.endsWith(";")&&(t+=";"),t}let n=e.trim();return n&&!n.endsWith(";")&&(n+=";"),n};buildHandlerFromRawBody(e,t){const{normalized:s,originalParam:n}=this.normalizeToArrow(e),r=this.renameEventParam(s,n),i=this.replaceThisReferences(r);return t?this.prefixBareIdentifiers(i,t):i}replaceThisReferences(e){return e.replace(/\bthis\./g,"event.target.")}isBareCall(e){return!e.includes("=>")&&PPHP._bareCallRe.test(e)&&!/^[A-Za-z_$]\w*_/.test(e)}normalizeToArrow(e){const t=e.match(/^\s*(?:\([\w\s,]*\)|[A-Za-z_$][\w$]*)\s*=>/);if(!t)return{normalized:`() => { ${e} }`,originalParam:null};const s=t[0].replace(/\s*=>\s*$/,"").trim().replace(/^\(|\)$/g,"").trim();return{normalized:e,originalParam:/^[A-Za-z_$]\w*$/.test(s)?s:null}}renameEventParam(e,t){if(!t||"event"===t)return e;const s=new RegExp(`\\b${this.escapeRegex(t)}\\b`,"g");return e.replace(s,((e,t,s)=>{const n=s[t-1],r=s[t+e.length];return n&&/[\w$]/.test(n)||r&&/[\w$]/.test(r)?e:"event"}))}escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}prefixBareIdentifiers(e,t){const s=e.indexOf("=>");if(-1!==s){const n=e.slice(0,s+2),r=e.slice(s+2);return n+this.prefixIds(r,t,new Set(["event"]))}const n=this.prefixIds(e,t,new Set(["event"]));return/^[A-Za-z_$].*\)$/.test(n.trim())?`() => ${n}`:`(event) => { ${n}; }`}async handleDebounce(e,t,s){const n=e.getAttribute("pp-debounce"),r=n?this.parseTime(n):0,i=e.getAttribute("pp-before-request")??"",a=e.getAttribute("pp-after-request")??"",o=PPHP._cancelableEvents,c=async n=>{o.has(t)&&n.cancelable&&n.preventDefault();try{const t=this.getScopeId(e);if(i){const s=t?`${t}_${i}`:i;await this.invokeHandler(e,s,n)}if(await this.invokeHandler(e,s,n),a&&!a.startsWith("@close")){const s=t?`${t}_${a}`:a;await this.invokeHandler(e,s,n)}this.handlerAutofocusAttribute()}catch(e){console.error("Error in debounced handler:",e)}},l={passive:PPHP._passiveEvents.has(t)&&!o.has(t)},h=`${t}::${e.__pphpId||e.tagName}`,p=e=>{if(r>0){const t=PPHP._debounceTimers.get(h);t&&clearTimeout(t);const s=setTimeout((()=>{PPHP._debounceTimers.delete(h),c(e)}),r);PPHP._debounceTimers.set(h,s)}else c(e)};e instanceof HTMLFormElement&&"submit"===t?e.addEventListener("submit",(e=>{e.cancelable&&e.preventDefault(),p(e)}),l):e.addEventListener(t,p,l)}debounce(e,t=300,s=!1){let n;return function(...r){const i=this;n&&clearTimeout(n),n=setTimeout((()=>{n=null,s||e.apply(i,r)}),t),s&&!n&&e.apply(i,r)}}handlerAutofocusAttribute(){const e=document.querySelector("dialog[open]");let t=null;if(e&&(t=e.querySelector("[pp-autofocus]")),t||(t=document.querySelector("[pp-autofocus]")),!t)return;const s=t.getAttribute("pp-autofocus");if(!this.isJsonLike(s))return;const n=this.parseJson(s);requestAnimationFrame((()=>{t.focus(),(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement)&&"function"==typeof this.setCursorPosition&&(t instanceof HTMLInputElement&&"number"===t.type?(t.type="text",this.setCursorPosition(t,n),t.type="number"):this.setCursorPosition(t,n))}))}async invokeHandler(e,t,s){this._activeSection=this.getScopeId(e);try{const n=t.trim();let r=this._handlerCache.get(n);r||(r=this.parseHandler(n),this._handlerCache.set(n,r)),await this.executeHandler(r,e,s,n)}catch(s){this.handleInvokeError(s,t,e)}finally{this.scheduleFlush()}}parseHandler(e){const t=e.replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").replace(/\s+/g," ").trim();if(this.isArrowFunction(t))return this.parseArrowFunction(t);const s=t.match(/^(\w+(?:\.\w+)*)\s*\(\s*(.*?)\s*\)$/s);if(s)return{type:"call",name:s[1],args:s[2],isAsync:this.isAsyncFunction(s[1])};const n=t.match(/^(\w+)$/);return n?{type:"simple",name:n[1],isAsync:this.isAsyncFunction(n[1])}:{type:"complex",body:t,isAsync:!1}}isArrowFunction(e){let t=!1,s="",n=0;for(let r=0;r<e.length-1;r++){const i=e[r],a=e[r+1];if(t||'"'!==i&&"'"!==i&&"`"!==i){if(t&&i===s&&"\\"!==e[r-1])t=!1,s="";else if(!t&&("("===i&&n++,")"===i&&n--,"="===i&&">"===a&&n>=0))return!0}else t=!0,s=i}return!1}parseArrowFunction(e){const t=this.findArrowIndex(e);let s=e.substring(t+2).trim();return s.startsWith("{")&&s.endsWith("}")&&(s=s.slice(1,-1).trim()),{type:"arrow",body:s,isAsync:e.includes("async")||this.containsAwait(s)}}findArrowIndex(e){let t=!1,s="";for(let n=0;n<e.length-1;n++){const r=e[n],i=e[n+1];if(t||'"'!==r&&"'"!==r&&"`"!==r){if(t&&r===s&&"\\"!==e[n-1])t=!1;else if(!t&&"="===r&&">"===i)return n}else t=!0,s=r}return-1}async executeArrowHandler(e,t,s){const n=this.parseStatements(e.body);let r=!1;for(const e of n)await this.executeSingleStatement(e,t,s)&&(r=!0);r||await this.executeDynamic(e.body,t,s)}async executeComplexHandler(e,t,s){await this.executeDynamic(e.body,t,s)}parseStatements(e){const t=[];let s="",n=0,r=!1,i="";for(let a=0;a<e.length;a++){const o=e[a];r||'"'!==o&&"'"!==o&&"`"!==o?r&&o===i&&"\\"!==e[a-1]&&(r=!1,i=""):(r=!0,i=o),r||("("!==o&&"{"!==o&&"["!==o||n++,")"!==o&&"}"!==o&&"]"!==o||n--,";"!==o||0!==n)?s+=o:s.trim()&&(t.push(s.trim()),s="")}return s.trim()&&t.push(s.trim()),t}async executeInlineModule(e,t,s,n,r){if(t&&t.trim())if(this.isJsonLike(t)){const r=this.parseJson(t);null!==r&&"object"==typeof r?await this.callInlineModule(e,{...r,element:s,event:n}):await this.callInlineModule(e,r)}else try{const s=this.getOrCreateEvaluator(t)(this.props);await this.callInlineModule(e,s)}catch{await this.callInlineModule(e,{element:s,event:n})}else await this.handleParsedCallback(s,r,n)}async executeSingleStatement(e,t,s){const n=e.trim();if(!n)return!1;const r=n.match(/^\(\s*\)\s*=>\s*(.+)$/);if(r)return await this.executeSingleStatement(r[1],t,s);if(/^\s*(if|for|while|switch|try|return|throw|var|let|const|function|class)\b/.test(n))return await this.executeDynamic(n,t,s),!0;const i=n.match(/^(\w+)\s*\(\s*(.*?)\s*\)$/s);if(i){const[,e,r]=i,a=this.resolveFunctionName(e);if(a&&this._inlineModuleFns.has(a))return await this.executeInlineModule(a,r,t,s,n),!0;if(a){const e=globalThis[a];if("function"==typeof e)return await this.executeGlobalFunction(e,r,t,s),!0}return await this.handleParsedCallback(t,n,s),!0}const a=n.match(/^(\w+)$/);if(a){const e=a[1],n=this.resolveFunctionName(e);if(n&&this._inlineModuleFns.has(n))return await this.handleParsedCallback(t,`${n}()`,s),!0;if(n){const e=globalThis[n];if("function"==typeof e)return e.call(globalThis,s),!0}return await this.handleParsedCallback(t,`${e}()`,s),!0}return await this.executeDynamic(n,t,s),!0}async executeCallHandler(e,t,s,n){const{name:r,args:i}=e,a=this.resolveFunctionName(r);if(a){if(this._inlineModuleFns.has(a))return void await this.executeInlineModule(a,i||"",t,s,n);const e=globalThis[a];if("function"==typeof e)return void await this.executeGlobalFunction(e,i||"",t,s)}await this.handleParsedCallback(t,n,s)}resolveFunctionName(e){if(this._inlineModuleFns.has(e))return e;if(!e.includes("_")&&"function"==typeof globalThis[e])return e;if(e.includes("_")){const[t,...s]=e.split("_"),n=s.join("_"),r=this._sectionParentMap.get(t);if(r){const e=`${r}_${n}`;if(this._inlineModuleFns.has(e))return e}if(this._inlineModuleFns.has(n))return n;if("function"==typeof globalThis[n])return n}return null}async executeSimpleHandler(e,t,s){const{name:n}=e,r=this.resolveFunctionName(n);if(r){if(this._inlineModuleFns.has(r))return void await this.handleParsedCallback(t,`${r}()`,s);const e=globalThis[r];if("function"==typeof e)return void e.call(globalThis,s)}await this.handleParsedCallback(t,`${n}()`,s)}async executeHandler(e,t,s,n){switch(e.type){case"arrow":await this.executeArrowHandler(e,t,s);break;case"call":await this.executeCallHandler(e,t,s,n);break;case"simple":await this.executeSimpleHandler(e,t,s);break;case"complex":await this.executeComplexHandler(e,t,s);break;default:await this.handleParsedCallback(t,n,s)}}async executeGlobalFunction(e,t,s,n){if(t.trim())if(this.isJsonLike(t)){const r=this.parseJson(t)??{};e.call(globalThis,{...r,element:s,event:n})}else{const r=this.getOrCreateProxy(this.props);new Function("event","proxy","props","fn",`with (proxy) { return fn(${t}); }`).call(s,n,r,this.props,e)}else e.call(globalThis,n)}async executeDynamic(e,t,s){const n=this.getOrCreateProxy(this.props);let r=e;this._activeSection&&(r=this.prefixFunctionCalls(e,this._activeSection));const i=new Function("event","proxy","props",`\n with (proxy) {\n ${r}\n }`);await i.call(t,s,n,this.props)}getOrCreateEvaluator(e){let t=this._evaluatorCache.get(e);return t||(t=this.makeSafeEvaluator(e),this._evaluatorCache.set(e,t)),t}getOrCreateProxy(e){let t=this._handlerProxyCache.get(e);return t||(t=this.createHandlerProxy(e),this._handlerProxyCache.set(e,t)),t}createHandlerProxy(e){const t=this._inlineModuleFns;return new Proxy(e,{get(e,s,n){if("string"==typeof s){if(t.has(s))return t.get(s);if(s in e){const t=Reflect.get(e,s,n),r=globalThis[s];if(!(null==t||"object"==typeof t&&0===Object.keys(t).length||PPHP._isBuiltIn(s)&&typeof t!=typeof r))return t}if(s in globalThis){const e=globalThis[s];return"function"==typeof e&&/^[a-z]/.test(s)?e.bind(globalThis):e}}return Reflect.get(e,s,n)},set:(e,t,s,n)=>Reflect.set(e,t,s,n),has:(e,s)=>"string"==typeof s&&t.has(s)||s in e||s in globalThis})}isAsyncFunction(e){const t=this._inlineModuleFns.get(e)||globalThis[e];return t&&("AsyncFunction"===t.constructor.name||t.toString().includes("async "))}containsAwait(e){return/\bawait\s+/.test(e)}handleInvokeError(e,t,s){const n=e instanceof Error?e.message:String(e),r=s.tagName+(s.id?`#${s.id}`:"");console.error(`Handler execution failed on ${r}:\nHandler: "${t}"\nError: ${n}`,e),s.dispatchEvent(new CustomEvent("pphp:handler-error",{detail:{handler:t,error:e,element:s},bubbles:!0}))}clearHandlerCaches(){this._handlerCache.clear(),this._evaluatorCache.clear()}async handleParsedCallback(e,t,s){const{funcName:n,data:r}=this.parseCallback(e,t);if(!n)return;const i=Array.isArray(n)?n:[n];let a;for(const e of i){const t=this._inlineModuleFns.get(e);if("function"==typeof t){a=t;break}const s=this[e];if("function"==typeof s){a=s;break}const n=window[e];if("function"==typeof n){a=n;break}}if(a){const t=e.hasAttribute("pp-after-request"),n=Array.isArray(r.args)?r.args:[],i=this._responseData?this.parseJson(this._responseData):{response:this._responseData};let o={args:n,element:e,data:r,event:s};return t&&(o={...o,...i}),void await a.call(this,o)}this._responseData=null,this._responseData=await this.handleUndefinedFunction(e,Array.isArray(n)?n[0]:n,r)}stripAutoPrefix(e){for(const t of PPHP._autoPrefixes)if(e.startsWith(t))return e.slice(t.length);return e}async handleUndefinedFunction(e,t,s){const n=this.stripAutoPrefix(t),r={callback:await this.encryptCallbackName(n),...s},i=this.createFetchOptions(r),a=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});try{this.saveElementOriginalState(e),this.handleSuspenseElement(e);const t=new URL(window.location.href);let r="",o="",c={success:!1};const l=e.querySelector("input[type='file']");if(l){if(r=await this.fetchFileWithData(t.href,n,l,s),o=this.extractJson(r)||"",o)try{c=this.parseJson(o)}catch(e){console.error("Error parsing JSON response. Please ensure the response is in valid JSON format.",e)}}else{const e=await this.fetch(t.href,i);if(r=await e.text(),this.getRedirectUrl(r))return void await this.redirect(this.getRedirectUrl(r)||"");if(o=this.extractJson(r)||"",o)try{c=this.parseJson(o)}catch(e){console.error("Error parsing JSON response. Please ensure the response is in valid JSON format.",e)}}const h=e.getAttribute("pp-before-request")||"",p=e.getAttribute("pp-after-request")||"";if((h||p&&c.success)&&this.restoreSuspenseElement(e),h||p){let e="";if(c.success){e=r.replace(o,"")}else e=r;if(this.appendAfterbegin(e),!p&&!c.success)return}if(p&&c.success){this.handleAfterRequest(p,o);const e=r.replace(o,"");return this.appendAfterbegin(e),o}if("@close"===p)return c.success?o:void 0;const d=await this.fetch(t.href,a),u=await d.text();if(this.getRedirectUrl(u))return void await this.redirect(this.getRedirectUrl(u)||"");await this.handleResponseRedirectOrUpdate(r,u,o,c)}catch(e){console.error(`Error handling undefined function "${n}". Please ensure the function is defined and accessible.`,e)}}handleAfterRequest(e,t){if(!this.isJsonLike(e))return;const s=this.parseJson(e),n=t?this.parseJson(t):null,r=s.targets;Array.isArray(r)&&r.forEach((e=>{const{id:t,...s}=e,r=document.querySelector(t);let i={};if(n){for(const t in s)if(s.hasOwnProperty(t))switch(t){case"innerHTML":case"outerHTML":case"textContent":case"innerText":"response"===s[t]&&(i[t]=e.responseKey?n[e.responseKey]:n.response);break;default:i[t]=s[t]}}else i=s;r&&this.updateElementAttributes(r,i)}))}sanitizePassiveHandlers(e){return e.replace(/\s+onwheel\s*=\s*(['"])([\s\S]*?)\1/gi,((e,t,s)=>` data-onwheel-code="${this.decodeEntities(s).replace(/"/g,"&quot;")}"`)).replace(/\s+onmousewheel\s*=\s*(['"])[\s\S]*?\1/gi,"")}handlePassiveWheelStashes(e){(e instanceof Document?e.body:e).querySelectorAll("[data-onwheel-code]").forEach((e=>{let t=this.decodeEntities(e.dataset.onwheelCode||"").trim();delete e.dataset.onwheelCode,e.onwheel=null;const s=this.getScopeId(e);if(s){const e=t.indexOf("=>");if(e>=0){const n=t.slice(0,e+2),r=t.slice(e+2);t=n+this.prefixIds(r,s)}else t=this.prefixIds(t,s)}e.removeAllEventListeners("wheel"),this.handleDebounce(e,"wheel",t)}))}async handleResponseRedirectOrUpdate(e,t,s,n){const r=this.sanitizePassiveHandlers(t),i=this.getUpdatedHTMLContent(e,s,n),a=(new DOMParser).parseFromString(r,"text/html");i&&a.body.insertAdjacentElement("afterbegin",i),this.updateBodyContent(a.body.outerHTML)}getUpdatedHTMLContent(e,t,s){const n=document.createElement("div");if(n.id="afterbegin-8D95D",s&&t?.success){const t=e.replace(s,"");n.innerHTML=t}else n.innerHTML=e;return n.innerHTML?n:null}async updateBodyContent(e){const t=this.saveScrollPositions();this.saveElementState();const s=(new DOMParser).parseFromString(e,"text/html");await this.appendCallbackResponse(s),this.restoreElementState(),this.restoreScrollPositions(t),await this.initReactiveOn(),this.attachWireFunctionEvents()}restoreElementState(){if(this._elementState.focusId){const e=document.getElementById(this._elementState.focusId)||document.querySelector(`[name="${this._elementState.focusId}"]`);if(e instanceof HTMLInputElement){const t=e.value.length||0;void 0!==this._elementState.focusSelectionStart&&null!==this._elementState.focusSelectionEnd&&e.setSelectionRange(t,t),this._elementState.focusValue&&("checkbox"===e.type||"radio"===e.type?e.checked=!!this._elementState.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._elementState.focusValue)),e.focus()}else if(e instanceof HTMLTextAreaElement){const t=e.value.length||0;void 0!==this._elementState.focusSelectionStart&&null!==this._elementState.focusSelectionEnd&&e.setSelectionRange(t,t),this._elementState.focusValue&&""!==e.value&&(e.value=this._elementState.focusValue),e.focus()}else e instanceof HTMLSelectElement&&(this._elementState.focusValue&&""!==e.value&&(e.value=this._elementState.focusValue),e.focus())}this._elementState.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)}saveElementState(){const e=document.activeElement;this._elementState.focusId=e?.id||e?.name,this._elementState.focusValue=e?.value,this._elementState.focusChecked=e?.checked,this._elementState.focusType=e?.type,this._elementState.focusSelectionStart=e?.selectionStart,this._elementState.focusSelectionEnd=e?.selectionEnd,this._elementState.isSuspense=e.hasAttribute("pp-suspense"),this._elementState.checkedElements.clear(),document.querySelectorAll('input[type="checkbox"]:checked').forEach((e=>{this._elementState.checkedElements.add(e.id||e.name)})),document.querySelectorAll('input[type="radio"]:checked').forEach((e=>{this._elementState.checkedElements.add(e.id||e.name)}))}updateElementAttributes(e,t){for(const s in t)if(t.hasOwnProperty(s))switch(s){case"innerHTML":case"outerHTML":case"textContent":case"innerText":e[s]=this.decodeHTML(t[s]);break;case"insertAdjacentHTML":e.insertAdjacentHTML(t.position||"beforeend",this.decodeHTML(t[s].html));break;case"insertAdjacentText":e.insertAdjacentText(t.position||"beforeend",this.decodeHTML(t[s].text));break;case"setAttribute":e.setAttribute(t.attrName,this.decodeHTML(t[s]));break;case"removeAttribute":e.removeAttribute(t[s]);break;case"className":e.className=this.decodeHTML(t[s]);break;case"classList.add":e.classList.add(...this.decodeHTML(t[s]).split(","));break;case"classList.remove":e.classList.remove(...this.decodeHTML(t[s]).split(","));break;case"classList.toggle":e.classList.toggle(this.decodeHTML(t[s]));break;case"classList.replace":const[n,r]=this.decodeHTML(t[s]).split(",");e.classList.replace(n,r);break;case"dataset":e.dataset[t.attrName]=this.decodeHTML(t[s]);break;case"style":Object.assign(e.style,t[s]);break;case"value":e.value=this.decodeHTML(t[s]);break;case"checked":e.checked=t[s];break;default:e.setAttribute(s,this.decodeHTML(t[s]))}}decodeHTML(e){const t=document.createElement("textarea");return t.innerHTML=e,t.value}appendAfterbegin(e){if(!e)return;const t="afterbegin-8D95D";let s=document.getElementById(t);s?(s.innerHTML=e,document.body.insertAdjacentElement("afterbegin",s)):(s=document.createElement("div"),s.id=t,s.innerHTML=e,document.body.insertAdjacentElement("afterbegin",s))}restoreSuspenseElement(e){const t=e.getAttribute("pp-original-state");if(e.hasAttribute("pp-suspense")&&t){const s=(e,t)=>{for(const s in t)t.hasOwnProperty(s)&&("textContent"===s?e.textContent=t[s]:"innerHTML"===s?e.innerHTML=t[s]:"disabled"===s?!0===t[s]?e.setAttribute("disabled","true"):e.removeAttribute("disabled"):e.setAttribute(s,t[s]));for(const s of Array.from(e.attributes))t.hasOwnProperty(s.name)||e.removeAttribute(s.name)},n=(e,t)=>{for(const n in t)if(t.hasOwnProperty(n))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 n=this.parseJson(e);s(t,n)}else r(t,e);t.removeAttribute("pp-original-state")}}},r=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},i=(e,t)=>{e instanceof HTMLFormElement?n(e,t):s(e,t)};try{const r=this.parseJson(t);if(r)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 n=this.parseJson(t);s(e,n)}}}const r=new FormData(e),i={};if(r.forEach(((e,t)=>{i[t]=e})),n(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(r.targets){r.targets.forEach((e=>{const{id:t,...s}=e,n=document.querySelector(t);n&&i(n,s)}));const{targets:t,...n}=r;s(e,n)}else{const{empty:t,...n}=r;s(e,n)}}catch(e){console.error(`Error parsing JSON: ${e instanceof Error?e.message:"Unknown error"}. Please ensure the JSON string is valid.`,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,s,n={}){const r=new FormData,i=s.files;if(i)for(let e=0;e<i.length;e++)r.append("file[]",i[e]);r.append("callback",t);for(const e in n)n.hasOwnProperty(e)&&r.append(e,n[e]);const a=await this.fetch(e,{method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:r});return await a.text()}async handleSuspenseElement(e){let t=e.getAttribute("pp-suspense")||"";const s=(e,t)=>{for(const s in t)if(t.hasOwnProperty(s))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 s=this.parseJson(e);"disabled"!==s.onsubmit&&this.updateElementAttributes(t,s),s.targets&&s.targets.forEach((e=>{const{id:t,...s}=e,n=document.querySelector(t);n&&r(n,s)}))}else n(t,e)}},n=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},r=(e,t)=>{e instanceof HTMLFormElement?s(e,t):this.updateElementAttributes(e,t)};try{if(t&&this.isJsonLike(t)){const n=this.parseJson(t);if(n)if(e instanceof HTMLFormElement){const t=new FormData(e),r={};t.forEach(((e,t)=>{r[t]=e})),n.disabled&&this.toggleFormElements(e,!0);const{disabled:i,...a}=n;this.updateElementAttributes(e,a),s(e,r)}else if(n.targets){n.targets.forEach((e=>{const{id:t,...s}=e,n=document.querySelector(t);n&&r(n,s)}));const{targets:t,...s}=n;this.updateElementAttributes(e,s)}else{if("disabled"===n.empty&&""===e.value)return;const{empty:t,...s}=n;this.updateElementAttributes(e,s)}}else if(t)n(e,t);else if(e instanceof HTMLFormElement){const t=new FormData(e),n={};t.forEach(((e,t)=>{n[t]=e})),s(e,n)}}catch(e){console.error(`Error parsing JSON: ${e instanceof Error?e.message:"Unknown error"}. Please ensure the JSON string is valid.`,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 s=0;s<e.attributes.length;s++){const n=e.attributes[s];t[n.name]=n.value}e.setAttribute("pp-original-state",JSON.stringify(t))}if(e instanceof HTMLFormElement){let t=null;const s=e.id;s&&(t=document.querySelector(`[form="${s}"]`)),s&&t||(t=Array.from(e.elements).find((e=>e instanceof HTMLButtonElement||e instanceof HTMLInputElement))),t?t.hasAttribute("pp-original-state")||this.saveElementOriginalState(t):console.warn("Warning: No invoker detected for the form. Ensure the form has an associated invoker or an ID for proper handling.")}e.querySelectorAll("[pp-suspense]").forEach((e=>this.saveElementOriginalState(e)))}getUrlParams(){const e={};return new URLSearchParams(window.location.search).forEach(((t,s)=>{e[s]=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 s={};const n=e.closest("form");if(n){new FormData(n).forEach(((e,t)=>{s[t]?Array.isArray(s[t])?s[t].push(e):s[t]=[s[t],e]:s[t]=e}))}else e instanceof HTMLInputElement?s=this.handleInputElement(e):(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(s[e.name]=e.value);const r=t.match(/^(\w+)\(([\s\S]*)\)$/);if(r){const e=r[1];let t=r[2].trim();if(t.startsWith("{")&&t.endsWith("}")||t.startsWith("[")&&t.endsWith("]"))if(this.isJsonLike(t))try{const e=this.parseJson(t);Array.isArray(e)?s.args=e:e&&"object"==typeof e&&(s={...s,...e})}catch(e){console.error("Error parsing JSON args:",e),s.rawArgs=t}else try{const e=this.evaluateJavaScriptObject(t);Array.isArray(e)?s.args=e:e&&"object"==typeof e?s={...s,...e}:s.rawArgs=t}catch(e){console.error("Error evaluating JS object args:",e),s.rawArgs=t}else try{const e=this.getOrCreateEvaluator(t)(this.props);s.args=[e]}catch{s.args=t.split(/,(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/).map((e=>e.trim().replace(/^['"]|['"]$/g,"")))}return{funcName:e,data:s}}return{funcName:t,data:s}}evaluateJavaScriptObject(e){try{const t=this.getOrCreateProxy(this.props);return new Function("proxy","Date","Math","JSON",`\n with (proxy) {\n return ${e};\n }\n `).call(null,t,Date,Math,JSON)}catch(e){throw console.error("Failed to evaluate JavaScript object:",e),e}}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 s=document.querySelector(`input[name="${e.name}"]:checked`);t[e.name]=s?s.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}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 s=parseInt(t.length,10)||0;e.setSelectionRange(s,s)}}handleInputAppendParams(e,t){const s=e.getAttribute("pp-append-params"),n=e.getAttribute("pp-append-params-sync");if("true"===s){if("true"===n){const t=e.name||e.id;if(t){const s=new URL(window.location.href),n=new URLSearchParams(s.search);n.has(t)&&(e.value=n.get(t)||"")}}e.addEventListener(t,(e=>{const t=e.currentTarget,s=t.value,n=new URL(window.location.href),r=new URLSearchParams(n.search),i=t.name||t.id;if(i){s?r.set(i,s):r.delete(i);const e=r.toString()?`${n.pathname}?${r.toString()}`:n.pathname;history.replaceState(null,"",e)}}))}}handleHiddenAttribute(){const e=document.querySelectorAll("[pp-visibility]"),t=document.querySelectorAll("[pp-display]"),s=this.handleElementVisibility.bind(this),n=this.handleElementDisplay.bind(this);e.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-visibility",s))),t.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-display",n)))}handleVisibilityElementAttribute(e,t,s){const n=e.getAttribute(t);if(n)if(this.isJsonLike(n)){s(e,this.parseJson(n))}else{const s=this.parseTime(n);if(s>0){const n="pp-visibility"===t?"visibility":"display",r="visibility"===n?"hidden":"none";this.scheduleChange(e,s,n,r)}}}handleElementVisibility(e,t){this.handleElementChange(e,t,"visibility","hidden","visible")}handleElementDisplay(e,t){this.handleElementChange(e,t,"display","none","block")}handleElementChange(e,t,s,n,r){const i=t.start?this.parseTime(t.start):0,a=t.end?this.parseTime(t.end):0;i>0?(e.style[s]=n,this.scheduleChange(e,i,s,r),a>0&&this.scheduleChange(e,i+a,s,n)):a>0&&this.scheduleChange(e,a,s,n)}handleAnchorTag(){document.querySelectorAll("a").forEach((e=>{e.addEventListener("click",(async e=>{const t=e.currentTarget,s=t.getAttribute("href"),n=t.getAttribute("target");if(s&&"_blank"!==n&&!e.metaKey&&!e.ctrlKey&&(e.preventDefault(),!this._isNavigating)){this._isNavigating=!0;try{if(/^(https?:)?\/\//i.test(s)&&!s.startsWith(window.location.origin))window.location.href=s;else{const e=t.getAttribute("pp-append-params");if(s.startsWith("?")&&"true"===e){const e=new URL(window.location.href),t=new URLSearchParams(e.search);let n="";const[r,i]=s.split("#");i&&(n=`#${i}`);new URLSearchParams(r.split("?")[1]).forEach(((e,s)=>{t.set(s,e)}));const a=`${e.pathname}?${t.toString()}${n}`;history.pushState(null,"",a)}else{const[e,t]=s.split("#"),n=`${e}${t?`#${t}`:""}`;history.pushState(null,"",n)}const n=s.indexOf("#");if(-1!==n){const e=s.slice(n+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){console.error("Anchor click error:",e)}finally{this._isNavigating=!1}}}))}))}handlePopState(){window.addEventListener("popstate",(async()=>{await this.handleNavigation()}))}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 void console.error(`Navigation error: ${t.status} ${t.statusText}`);const s=await t.text(),n=s.match(this._redirectRegex);if(n&&n[1])return void await this.redirect(n[1]);await this.updateDocumentContent(s)}catch(e){console.error("Navigation error:",e)}}findLoadingElement(e,t){let s=t;for(;;){const t=e.querySelector(`div[pp-loading-url='${s}']`);if(t)return t;if("/"===s)break;const n=s.lastIndexOf("/");s=n<=0?"/":s.substring(0,n)}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:s,fadeOut:n}=this.parseTransition(e);await this.fadeOut(t,n),t.innerHTML=e.innerHTML,this.fadeIn(t,s)}parseTransition(e){let t=250,s=250;const n=e.querySelector("[pp-loading-transition]"),r=n?.getAttribute("pp-loading-transition");if(r){const e=this.parseJson(r);e&&"object"==typeof e?(t=this.parseTime(e.fadeIn??t),s=this.parseTime(e.fadeOut??s)):console.warn("pp-loading-transition is not valid JSON → default values (250 ms) will be used. String:",r)}return{fadeIn:t,fadeOut:s}}fadeOut(e,t){return new Promise((s=>{e.style.transition=`opacity ${t}ms ease-out`,e.style.opacity="0",setTimeout((()=>{e.style.transition="",s()}),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(),s=this.sanitizePassiveHandlers(e),n=(new DOMParser).parseFromString(s,"text/html"),r="pp-dynamic-script",i="pp-dynamic-link";document.head.querySelectorAll("[pp-dynamic-meta]").forEach((e=>e.remove()));document.head.querySelectorAll(`[${i}]`).forEach((e=>e.remove()));document.head.querySelectorAll(`[${r}]`).forEach((e=>e.remove()));this.resetProps(),await(async e=>{Array.from(e.head.children).forEach((e=>{const t=e.tagName;if("SCRIPT"===t&&e.hasAttribute(r)){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,s=e.getAttribute("property"),n=document.head.querySelector(t?`meta[name="${t}"]`:`meta[property="${s}"]`),r=document.head.querySelector("title");n?document.head.replaceChild(e.cloneNode(!0),n):r?.nextSibling?document.head.insertBefore(e.cloneNode(!0),r.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 s=document.head.querySelector('link[rel="icon"]');if(s)document.head.replaceChild(e.cloneNode(!0),s);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.initReactiveOn(e.body),await this.populateDocumentBody(e)})(n),this.restoreScrollPositions(t),this.attachWireFunctionEvents(),this.handlerAutofocusAttribute()}restoreScrollPositions(e){requestAnimationFrame((()=>{const t=e.window;t&&window.scrollTo(t.scrollLeft,t.scrollTop),document.querySelectorAll("*").forEach((t=>{const s=this.getElementKey(t);e[s]&&(t.scrollTop=e[s].scrollTop,t.scrollLeft=e[s].scrollLeft)}))}))}PRESERVE_HANDLERS={DETAILS:(e,t)=>(t.open=e.open,!0),INPUT(e,t){const s=e,n=t;return s.value!==n.value&&(n.value=s.value),n.checked=s.checked,document.activeElement!==s||(null!=s.selectionStart&&(n.selectionStart=s.selectionStart,n.selectionEnd=s.selectionEnd),!1)},TEXTAREA(e,t){const s=e,n=t;return s.value!==n.value&&(n.value=s.value),document.activeElement!==s||(n.selectionStart=s.selectionStart,n.selectionEnd=s.selectionEnd,!1)},SELECT(e,t){const s=e;return t.selectedIndex=s.selectedIndex,document.activeElement!==s},VIDEO(e,t){const s=e,n=t;return n.currentTime=s.currentTime,s.paused?n.pause():n.play(),!0},AUDIO:(e,t)=>this.PRESERVE_HANDLERS.VIDEO(e,t),CANVAS:()=>!1};async populateDocumentBody(e){try{const t=document.body,s=e.body;this._wheelHandlersStashed||(document.querySelectorAll("[onwheel]").forEach((e=>{const t=e.getAttribute("onwheel").trim();if(e.removeAttribute("onwheel"),t){const s=new Function("event",t);e.addEventListener("wheel",s,{passive:!0})}})),this._wheelHandlersStashed=!0);const n=this.PRESERVE_HANDLERS;morphdom(t,s,{getNodeKey(e){if(e.nodeType!==Node.ELEMENT_NODE)return;const t=e;return t.hasAttribute("pp-sync-script")?`pp-sync-script:${t.getAttribute("pp-sync-script")}`:t.getAttribute("key")||void 0},onBeforeElUpdated(e,t){const s=e.tagName;if("SCRIPT"===s||e.hasAttribute("data-nomorph"))return!1;const r=n[s];return!r||r(e,t)},onBeforeNodeDiscarded:e=>(e instanceof HTMLElement&&e.dataset.timerId&&clearTimeout(Number(e.dataset.timerId)),!0)})}catch(e){console.error("Error populating document body:",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){console.error("Redirect error:",e)}}abortActiveRequest(){this._activeAbortController&&this._activeAbortController.abort()}async fetch(e,t,s=!1){let n;return s?(this._activeAbortController&&this._activeAbortController.abort(),this._activeAbortController=new AbortController,n=this._activeAbortController):n=new AbortController,fetch(e,{...t,signal:n.signal,headers:{...t?.headers,"X-PPHP-Navigation":"partial","X-Requested-With":"XMLHttpRequest"}})}isJsonLike(e){if("string"!=typeof e)return!1;const t=e.trim();return!(!/^\{[\s\S]*\}$/.test(t)&&!/^\[[\s\S]*\]$/.test(t))&&!(t.includes("(")||t.includes(")")||t.includes("=>"))}parseJson(e){try{return JSON5.parse(e)}catch(e){return console.error(`Error parsing JSON: ${e.message}. Please ensure the JSON string is valid.`,e),{}}}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":default:return e;case"s":return 1e3*e;case"m":return 60*e*1e3}}return 0}scheduleChange(e,t,s,n){setTimeout((()=>{requestAnimationFrame((()=>{e.style[s]=n}))}),t)}async fetchFunction(e,t={},s=!1){try{const n={callback:e,...t},r=window.location.href;let i;if(Object.keys(n).some((e=>{const t=n[e];return t instanceof File||t instanceof FileList&&t.length>0}))){const e=new FormData;Object.keys(n).forEach((t=>{const s=n[t];s instanceof File?e.append(t,s):s instanceof FileList?Array.from(s).forEach((s=>e.append(t,s))):e.append(t,s)})),i={method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:e}}else i=this.createFetchOptions(n);const a=await this.fetch(r,i,s);if(!a.ok)throw new Error(`Fetch failed with status: ${a.status} ${a.statusText}`);const o=await a.text();try{return JSON.parse(o)}catch{return o}}catch(e){throw console.error("Error in fetchFunction:",e),new Error("Failed to fetch data.")}}processSyncScripts(e){e.forEach((e=>{const t=`script[pp-sync-script="${CSS.escape(e)}"]`,s=document.querySelector(t);if(s){s.remove();const e=document.createElement("script");Array.from(s.attributes).forEach((t=>{e.setAttribute(t.name,t.value)})),s.src?e.src=s.src:e.textContent=s.textContent,e.type=s.type||"module",document.body.appendChild(e)}}))}async sync(...e){try{const t=this.saveScrollPositions();this.saveElementState();const s=e.length>0?e.map((e=>`pp-sync="${e}"`)):['pp-sync="true"'],n=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()}),r=await this.fetch(window.location.href,n),i=await r.text(),a=(new DOMParser).parseFromString(i,"text/html"),o=new Set;s.forEach((e=>{const t=document.querySelectorAll(`[${e}]`),s=a.body.querySelectorAll(`[${e}]`);t.forEach(((e,t)=>{const n=s[t];if(n){if(n.hasAttribute("pp-sync-script")){const e=n.getAttribute("pp-sync-script")||"";e&&o.add(e)}n.querySelectorAll("[pp-sync-script]").forEach((e=>{const t=e.getAttribute("pp-sync-script")||"";t&&o.add(t)})),e.innerHTML=n.innerHTML,this.reRunScripts(e)}}))})),this.processSyncScripts(o),this.restoreElementState(),this.restoreScrollPositions(t),this.attachWireFunctionEvents()}catch(e){console.error("Error in pphpSync:",e)}}async fetchAndUpdateBodyContent(){const e=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});this.abortActiveRequest();const t=await this.fetch(window.location.href,e,!0),s=await t.text();await this.updateBodyContent(s)}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,s,n,r="img",i=2e3){if(!(e instanceof HTMLElement))return;const a=e.closest(`.${t}`)?.querySelector("pre code"),o=a?.textContent?.trim()||"";o?navigator.clipboard.writeText(o).then((()=>{const t=e.querySelector(r);if(t)for(const[e,s]of Object.entries(n))e in t?t[e]=s:t.setAttribute(e,s);setTimeout((()=>{if(t)for(const[e,n]of Object.entries(s))e in t?t[e]=n:t.setAttribute(e,n)}),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{state;static instance=null;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})}}}class SearchParamsManager{static instance=null;listeners=[];constructor(){}static getInstance(){return SearchParamsManager.instance||(SearchParamsManager.instance=new SearchParamsManager),SearchParamsManager.instance}get params(){return new URLSearchParams(window.location.search)}get(e){return this.params.get(e)}set(e,t){const s=this.params;s.set(e,t),this.updateURL(s)}delete(e){const t=this.params;t.delete(e),this.updateURL(t)}replace(e){const t=new URLSearchParams;for(const s in e){const n=e[s];null!==n&&t.set(s,n)}this.updateURL(t,!0)}updateURL(e,t=!1){const s=`${window.location.pathname}?${e.toString()}`;t?history.replaceState(null,"",s):history.pushState(null,"",s),this.notifyListeners(e)}listen(e){this.listeners.push(e)}notifyListeners(e){for(const t of this.listeners)t(e)}enablePopStateListener(){window.addEventListener("popstate",(()=>{this.notifyListeners(this.params)}))}}var pphp=PPHP.instance,store=PPHPLocalStore.getInstance(),searchParams=SearchParamsManager.getInstance();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-prisma-php-app",
3
- "version": "3.0.0-beta.9",
3
+ "version": "3.0.0-rc.1",
4
4
  "description": "Prisma-PHP: A Revolutionary Library Bridging PHP with Prisma ORM",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",