create-prisma-php-app 2.3.0 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap.php +4 -8
- package/dist/index.js +6 -6
- package/dist/src/Lib/IncludeTracker.php +64 -0
- package/dist/src/Lib/MainLayout.php +25 -15
- package/dist/src/Lib/PHPX/IPHPX.php +0 -7
- package/dist/src/Lib/PHPX/PHPX.php +30 -39
- package/dist/src/Lib/PHPX/TemplateCompiler.php +137 -161
- package/dist/src/app/js/index.js +1 -1
- package/dist/src/app/js/morphdom-umd.min.js +1 -0
- package/package.json +1 -1
package/dist/bootstrap.php
CHANGED
|
@@ -540,7 +540,6 @@ final class Bootstrap
|
|
|
540
540
|
public static function wireCallback()
|
|
541
541
|
{
|
|
542
542
|
try {
|
|
543
|
-
// Initialize response
|
|
544
543
|
$response = [
|
|
545
544
|
'success' => false,
|
|
546
545
|
'error' => 'Callback not provided',
|
|
@@ -550,13 +549,10 @@ final class Bootstrap
|
|
|
550
549
|
$callbackResponse = null;
|
|
551
550
|
$data = [];
|
|
552
551
|
|
|
553
|
-
// Process form data
|
|
554
552
|
if (!empty($_FILES)) {
|
|
555
553
|
$data = $_POST;
|
|
556
554
|
|
|
557
|
-
// Iterate over each file key in $_FILES
|
|
558
555
|
foreach ($_FILES as $key => $file) {
|
|
559
|
-
// Check if it's a multiple file upload or a single file upload
|
|
560
556
|
if (is_array($file['name'])) {
|
|
561
557
|
$files = [];
|
|
562
558
|
foreach ($file['name'] as $index => $name) {
|
|
@@ -582,13 +578,14 @@ final class Bootstrap
|
|
|
582
578
|
}
|
|
583
579
|
}
|
|
584
580
|
|
|
585
|
-
// Validate and call the dynamic function
|
|
586
581
|
if (isset($data['callback'])) {
|
|
587
582
|
$callbackName = preg_replace('/[^a-zA-Z0-9_]/', '', $data['callback']);
|
|
588
583
|
|
|
589
|
-
if (
|
|
584
|
+
if (strpos($callbackName, '_') === 0) {
|
|
585
|
+
$response['error'] = 'Invalid callback';
|
|
586
|
+
} elseif (function_exists($callbackName) && is_callable($callbackName)) {
|
|
590
587
|
$dataObject = self::convertToArrayObject($data);
|
|
591
|
-
|
|
588
|
+
|
|
592
589
|
$callbackResponse = call_user_func($callbackName, $dataObject);
|
|
593
590
|
$response = [
|
|
594
591
|
'success' => true,
|
|
@@ -608,7 +605,6 @@ final class Bootstrap
|
|
|
608
605
|
$response['error'] = 'No callback provided';
|
|
609
606
|
}
|
|
610
607
|
|
|
611
|
-
// Output the JSON response only if the callbackResponse is not null or if there's an error
|
|
612
608
|
if ($callbackResponse !== null || isset($response['error'])) {
|
|
613
609
|
echo json_encode($response);
|
|
614
610
|
}
|
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 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"},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.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,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/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}"`;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}}
|
|
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"},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.dev=`npm-run-all projectName -p browserSync ${c.join(" ")}`,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}"`;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,21 +55,21 @@ async function installComposerDependencies(baseDir, dependencies) {
|
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
57
|
const npmPinnedVersions = {
|
|
58
|
-
"@tailwindcss/postcss": "^4.1.
|
|
58
|
+
"@tailwindcss/postcss": "^4.1.4",
|
|
59
59
|
"@types/browser-sync": "^2.29.0",
|
|
60
|
-
"@types/node": "^22.
|
|
60
|
+
"@types/node": "^22.15.2",
|
|
61
61
|
"@types/prompts": "^2.4.9",
|
|
62
62
|
"browser-sync": "^3.0.4",
|
|
63
63
|
chalk: "^5.4.1",
|
|
64
64
|
"chokidar-cli": "^3.0.0",
|
|
65
65
|
cssnano: "^7.0.6",
|
|
66
|
-
"http-proxy-middleware": "^3.0.
|
|
66
|
+
"http-proxy-middleware": "^3.0.5",
|
|
67
67
|
"npm-run-all": "^4.1.5",
|
|
68
|
-
"php-parser": "^3.2.
|
|
68
|
+
"php-parser": "^3.2.3",
|
|
69
69
|
postcss: "^8.5.3",
|
|
70
70
|
"postcss-cli": "^11.0.1",
|
|
71
71
|
prompts: "^2.4.2",
|
|
72
|
-
tailwindcss: "^4.1.
|
|
72
|
+
tailwindcss: "^4.1.4",
|
|
73
73
|
tsx: "^4.19.3",
|
|
74
74
|
typescript: "^5.8.3",
|
|
75
75
|
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Lib;
|
|
4
|
+
|
|
5
|
+
use RuntimeException;
|
|
6
|
+
use InvalidArgumentException;
|
|
7
|
+
|
|
8
|
+
class IncludeTracker
|
|
9
|
+
{
|
|
10
|
+
public static array $sections = [];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Includes and echoes a file wrapped in a unique pp-section-id container.
|
|
14
|
+
* Supported $mode values: 'include', 'include_once', 'require', 'require_once'
|
|
15
|
+
*
|
|
16
|
+
* @param string $filePath The path to the file to be included.
|
|
17
|
+
* @param string $mode The mode of inclusion. Can be 'include', 'include_once', 'require', or 'require_once'.
|
|
18
|
+
* @throws RuntimeException If the file does not exist.
|
|
19
|
+
* @throws InvalidArgumentException If an invalid mode is provided.
|
|
20
|
+
* @return void
|
|
21
|
+
*/
|
|
22
|
+
public static function render(string $filePath, string $mode = 'include_once'): void
|
|
23
|
+
{
|
|
24
|
+
if (!file_exists($filePath)) {
|
|
25
|
+
throw new RuntimeException("File not found: $filePath");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
ob_start();
|
|
29
|
+
|
|
30
|
+
switch ($mode) {
|
|
31
|
+
case 'include':
|
|
32
|
+
include $filePath;
|
|
33
|
+
break;
|
|
34
|
+
case 'include_once':
|
|
35
|
+
include_once $filePath;
|
|
36
|
+
break;
|
|
37
|
+
case 'require':
|
|
38
|
+
require $filePath;
|
|
39
|
+
break;
|
|
40
|
+
case 'require_once':
|
|
41
|
+
require_once $filePath;
|
|
42
|
+
break;
|
|
43
|
+
default:
|
|
44
|
+
throw new InvalidArgumentException("Invalid include mode: $mode");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
$output = ob_get_clean();
|
|
48
|
+
$wrapped = self::wrapWithId($filePath, $output);
|
|
49
|
+
|
|
50
|
+
self::$sections[$filePath] = [
|
|
51
|
+
'path' => $filePath,
|
|
52
|
+
'html' => $wrapped,
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
echo $wrapped;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private static function wrapWithId(string $filePath, string $html): string
|
|
59
|
+
{
|
|
60
|
+
$id = 's' . base_convert(sprintf('%u', crc32($filePath)), 10, 36);
|
|
61
|
+
|
|
62
|
+
return "<div pp-section-id=\"$id\">\n$html\n</div>";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -100,24 +100,34 @@ class MainLayout
|
|
|
100
100
|
|
|
101
101
|
foreach (self::$footerScripts->values() as $script) {
|
|
102
102
|
if (preg_match('/<!-- class:([^\s]+) -->/', $script, $matches)) {
|
|
103
|
-
$
|
|
103
|
+
$rawClassName = $matches[1];
|
|
104
104
|
$script = preg_replace('/<!-- class:[^\s]+ -->\s*/', '', $script, 1);
|
|
105
105
|
|
|
106
106
|
if (str_starts_with(trim($script), '<script')) {
|
|
107
|
-
$script = preg_replace_callback(
|
|
108
|
-
|
|
109
|
-
$
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
$attrs
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
107
|
+
$script = preg_replace_callback(
|
|
108
|
+
'/<script\b([^>]*)>/i',
|
|
109
|
+
function ($m) use ($rawClassName) {
|
|
110
|
+
$attrs = $m[1];
|
|
111
|
+
|
|
112
|
+
$attrs = preg_replace(
|
|
113
|
+
'/\btype\s*=\s*("[^"]*"|\'[^\']*\'|\S+)/i',
|
|
114
|
+
'',
|
|
115
|
+
$attrs
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
$encodedClass = 's' . base_convert(sprintf('%u', crc32($rawClassName)), 10, 36);
|
|
119
|
+
|
|
120
|
+
if (!str_contains($attrs, 'pp-sync-script=')) {
|
|
121
|
+
$attrs .= " pp-sync-script=\"{$encodedClass}\"";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
$attrs .= ' type="text/php"';
|
|
125
|
+
|
|
126
|
+
return "<script{$attrs}>";
|
|
127
|
+
},
|
|
128
|
+
$script,
|
|
129
|
+
1
|
|
130
|
+
);
|
|
121
131
|
}
|
|
122
132
|
}
|
|
123
133
|
|
|
@@ -17,13 +17,6 @@ interface IPHPX
|
|
|
17
17
|
*/
|
|
18
18
|
public function __construct(array $props = []);
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* Registers or initializes any necessary components or settings. (Placeholder method).
|
|
22
|
-
*
|
|
23
|
-
* @param array<string, mixed> $props Optional properties to customize the component.
|
|
24
|
-
*/
|
|
25
|
-
public static function init(array $props = []): void;
|
|
26
|
-
|
|
27
20
|
/**
|
|
28
21
|
* Renders the component with the given properties and children.
|
|
29
22
|
*
|
|
@@ -5,6 +5,7 @@ namespace Lib\PHPX;
|
|
|
5
5
|
use Lib\PHPX\IPHPX;
|
|
6
6
|
use Lib\PHPX\TwMerge;
|
|
7
7
|
use Lib\PrismaPHPSettings;
|
|
8
|
+
use Exception;
|
|
8
9
|
|
|
9
10
|
class PHPX implements IPHPX
|
|
10
11
|
{
|
|
@@ -40,16 +41,6 @@ class PHPX implements IPHPX
|
|
|
40
41
|
$this->class = $props['class'] ?? '';
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
/**
|
|
44
|
-
* Registers or initializes any necessary components or settings. (Placeholder method).
|
|
45
|
-
*
|
|
46
|
-
* @param array<string, mixed> $props Optional properties to customize the initialization.
|
|
47
|
-
*/
|
|
48
|
-
public static function init(array $props = []): void
|
|
49
|
-
{
|
|
50
|
-
// Register the component or any necessary initialization
|
|
51
|
-
}
|
|
52
|
-
|
|
53
44
|
/**
|
|
54
45
|
* Combines and returns the CSS classes for the component.
|
|
55
46
|
*
|
|
@@ -96,42 +87,42 @@ class PHPX implements IPHPX
|
|
|
96
87
|
}
|
|
97
88
|
|
|
98
89
|
/**
|
|
99
|
-
*
|
|
100
|
-
* Excludes 'class' and 'children' props from being added as attributes.
|
|
101
|
-
* Prioritizes attributes from `$this->props` if duplicates are found in `$params`.
|
|
90
|
+
* Build an HTML-attribute string.
|
|
102
91
|
*
|
|
103
|
-
*
|
|
92
|
+
* • Always ignores "class" and "children".
|
|
93
|
+
* • $params overrides anything in $this->props.
|
|
94
|
+
* • Pass names in $exclude to drop them for this call.
|
|
104
95
|
*
|
|
105
|
-
* @
|
|
96
|
+
* @param array $params Extra / overriding attributes (optional)
|
|
97
|
+
* @param array $exclude Attribute names to remove on the fly (optional)
|
|
98
|
+
* @return string Example: id="btn" data-id="7"
|
|
106
99
|
*/
|
|
107
|
-
protected function getAttributes(
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
100
|
+
protected function getAttributes(
|
|
101
|
+
array $params = [],
|
|
102
|
+
array $exclude = []
|
|
103
|
+
): string {
|
|
104
|
+
$reserved = ['class', 'children'];
|
|
105
|
+
|
|
106
|
+
$filtered = array_diff_key(
|
|
111
107
|
$this->props,
|
|
112
|
-
|
|
113
|
-
return !in_array($key, ["class", "children"]);
|
|
114
|
-
},
|
|
115
|
-
ARRAY_FILTER_USE_KEY
|
|
108
|
+
array_flip([...$reserved, ...$exclude])
|
|
116
109
|
);
|
|
117
110
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
$attributeStrings[] = "$escapedKey='$escapedValue'";
|
|
131
|
-
}
|
|
111
|
+
$attributes = array_merge($filtered, $params);
|
|
112
|
+
|
|
113
|
+
$pairs = array_map(
|
|
114
|
+
static fn($k, $v) =>
|
|
115
|
+
sprintf(
|
|
116
|
+
"%s='%s'",
|
|
117
|
+
htmlspecialchars($k, ENT_QUOTES, 'UTF-8'),
|
|
118
|
+
htmlspecialchars((string) $v, ENT_QUOTES, 'UTF-8')
|
|
119
|
+
),
|
|
120
|
+
array_keys($attributes),
|
|
121
|
+
$attributes
|
|
122
|
+
);
|
|
132
123
|
|
|
133
124
|
$this->attributesArray = $attributes;
|
|
134
|
-
return implode(
|
|
125
|
+
return implode(' ', $pairs);
|
|
135
126
|
}
|
|
136
127
|
|
|
137
128
|
/**
|
|
@@ -164,7 +155,7 @@ class PHPX implements IPHPX
|
|
|
164
155
|
{
|
|
165
156
|
try {
|
|
166
157
|
return $this->render();
|
|
167
|
-
} catch (
|
|
158
|
+
} catch (Exception) {
|
|
168
159
|
return ''; // Return an empty string or a fallback message in case of errors
|
|
169
160
|
}
|
|
170
161
|
}
|
|
@@ -13,6 +13,7 @@ use DOMNode;
|
|
|
13
13
|
use DOMText;
|
|
14
14
|
use RuntimeException;
|
|
15
15
|
use Bootstrap;
|
|
16
|
+
use LibXMLError;
|
|
16
17
|
|
|
17
18
|
class TemplateCompiler
|
|
18
19
|
{
|
|
@@ -35,6 +36,7 @@ class TemplateCompiler
|
|
|
35
36
|
'track',
|
|
36
37
|
'wbr'
|
|
37
38
|
];
|
|
39
|
+
private static array $sectionStack = [];
|
|
38
40
|
|
|
39
41
|
public static function compile(string $templateContent): string
|
|
40
42
|
{
|
|
@@ -43,15 +45,13 @@ class TemplateCompiler
|
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
$dom = self::convertToXml($templateContent);
|
|
46
|
-
|
|
47
48
|
$root = $dom->documentElement;
|
|
48
49
|
|
|
49
|
-
$
|
|
50
|
+
$output = [];
|
|
50
51
|
foreach ($root->childNodes as $child) {
|
|
51
|
-
$
|
|
52
|
+
$output[] = self::processNode($child);
|
|
52
53
|
}
|
|
53
|
-
|
|
54
|
-
return implode('', $outputParts);
|
|
54
|
+
return implode('', $output);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
public static function injectDynamicContent(string $htmlContent): string
|
|
@@ -77,10 +77,10 @@ class TemplateCompiler
|
|
|
77
77
|
|
|
78
78
|
$styleBlock = <<<HTML
|
|
79
79
|
<style>
|
|
80
|
-
body {
|
|
80
|
+
html:not([data-initial-hydrated]) body {
|
|
81
81
|
opacity: 0;
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
html[data-initial-hydrated] body {
|
|
84
84
|
opacity: 1;
|
|
85
85
|
}
|
|
86
86
|
</style>
|
|
@@ -113,160 +113,106 @@ class TemplateCompiler
|
|
|
113
113
|
{
|
|
114
114
|
return preg_replace_callback(
|
|
115
115
|
'/&(.*?)/',
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (preg_match('/^&(?:[a-zA-Z]+|#[0-9]+|#x[0-9A-Fa-f]+);$/', $str)) {
|
|
120
|
-
return $str;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return '&' . substr($str, 1);
|
|
124
|
-
},
|
|
116
|
+
fn($m) => preg_match('/^&(?:[a-zA-Z]+|#[0-9]+|#x[0-9A-Fa-f]+);$/', $m[0])
|
|
117
|
+
? $m[0]
|
|
118
|
+
: '&' . substr($m[0], 1),
|
|
125
119
|
$content
|
|
126
120
|
);
|
|
127
121
|
}
|
|
128
122
|
|
|
129
123
|
private static function escapeAttributeAngles(string $html): string
|
|
130
124
|
{
|
|
131
|
-
// Replace < and > inside any quoted attribute value
|
|
132
125
|
return preg_replace_callback(
|
|
133
126
|
'/(\s[\w:-]+=)([\'"])(.*?)\2/s',
|
|
134
|
-
|
|
135
|
-
$prefix = $m[1];
|
|
136
|
-
$quote = $m[2];
|
|
137
|
-
// < > *only* if bracket is not already escaped*
|
|
138
|
-
$value = str_replace(['<', '>'], ['<', '>'], $m[3]);
|
|
139
|
-
return $prefix . $quote . $value . $quote;
|
|
140
|
-
},
|
|
127
|
+
fn($m) => $m[1] . $m[2] . str_replace(['<', '>'], ['<', '>'], $m[3]) . $m[2],
|
|
141
128
|
$html
|
|
142
129
|
);
|
|
143
130
|
}
|
|
144
131
|
|
|
145
132
|
public static function convertToXml(string $templateContent): DOMDocument
|
|
146
133
|
{
|
|
147
|
-
$templateContent = self::escapeAttributeAngles($templateContent);
|
|
148
|
-
$templateContent = self::escapeAmpersands($templateContent);
|
|
149
|
-
|
|
134
|
+
$templateContent = self::escapeAttributeAngles(self::escapeAmpersands($templateContent));
|
|
150
135
|
$dom = new DOMDocument();
|
|
151
136
|
libxml_use_internal_errors(true);
|
|
152
137
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (!$dom->loadXML($wrappedContent)) {
|
|
138
|
+
if (!$dom->loadXML("<root>{$templateContent}</root>")) {
|
|
156
139
|
$errors = self::getXmlErrors();
|
|
157
|
-
throw new RuntimeException(
|
|
158
|
-
"XML Parsing Failed: " . implode("; ", $errors)
|
|
159
|
-
);
|
|
140
|
+
throw new RuntimeException("XML Parsing Failed: " . implode("; ", $errors));
|
|
160
141
|
}
|
|
142
|
+
|
|
161
143
|
libxml_clear_errors();
|
|
162
144
|
libxml_use_internal_errors(false);
|
|
163
|
-
|
|
164
145
|
return $dom;
|
|
165
146
|
}
|
|
166
147
|
|
|
167
148
|
protected static function getXmlErrors(): array
|
|
168
149
|
{
|
|
169
150
|
$errors = libxml_get_errors();
|
|
170
|
-
$errorMessages = [];
|
|
171
|
-
|
|
172
|
-
foreach ($errors as $error) {
|
|
173
|
-
$errorMessages[] = self::formatLibxmlError($error);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
151
|
libxml_clear_errors();
|
|
177
|
-
return $
|
|
152
|
+
return array_map(fn($e) => self::formatLibxmlError($e), $errors);
|
|
178
153
|
}
|
|
179
154
|
|
|
180
|
-
protected static function formatLibxmlError(
|
|
155
|
+
protected static function formatLibxmlError(LibXMLError $error): string
|
|
181
156
|
{
|
|
182
|
-
$
|
|
183
|
-
LIBXML_ERR_WARNING =>
|
|
184
|
-
LIBXML_ERR_ERROR
|
|
185
|
-
LIBXML_ERR_FATAL
|
|
186
|
-
default
|
|
157
|
+
$type = match ($error->level) {
|
|
158
|
+
LIBXML_ERR_WARNING => 'Warning',
|
|
159
|
+
LIBXML_ERR_ERROR => 'Error',
|
|
160
|
+
LIBXML_ERR_FATAL => 'Fatal',
|
|
161
|
+
default => 'Unknown',
|
|
187
162
|
};
|
|
188
|
-
|
|
189
|
-
$message = trim($error->message);
|
|
190
|
-
if (preg_match("/tag (.*?) /", $message, $matches)) {
|
|
191
|
-
$tag = $matches[1];
|
|
192
|
-
$message = str_replace($tag, "`{$tag}`", $message);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
163
|
return sprintf(
|
|
196
|
-
"[%s] Line %d,
|
|
197
|
-
$
|
|
164
|
+
"[%s] Line %d, Col %d: %s",
|
|
165
|
+
$type,
|
|
198
166
|
$error->line,
|
|
199
167
|
$error->column,
|
|
200
|
-
$message
|
|
168
|
+
trim($error->message)
|
|
201
169
|
);
|
|
202
170
|
}
|
|
203
171
|
|
|
204
172
|
protected static function processNode(DOMNode $node, bool $inBody = false): string
|
|
205
173
|
{
|
|
206
174
|
if ($node instanceof DOMText) {
|
|
207
|
-
|
|
208
|
-
$text = preg_replace_callback(
|
|
209
|
-
'/{{\s*(.+?)\s*}}/u',
|
|
210
|
-
function ($matches) {
|
|
211
|
-
$expr = trim($matches[1]);
|
|
212
|
-
if (preg_match('/^[\w.]+$/u', $expr)) {
|
|
213
|
-
return "<span pp-bind=\"{$expr}\"></span>";
|
|
214
|
-
} else {
|
|
215
|
-
$encodedExpr = htmlspecialchars($expr, ENT_QUOTES, 'UTF-8');
|
|
216
|
-
return "<span pp-bind-expr=\"{$encodedExpr}\"></span>";
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
$text
|
|
220
|
-
);
|
|
221
|
-
return $text;
|
|
175
|
+
return self::processTextNode($node);
|
|
222
176
|
}
|
|
223
177
|
|
|
224
178
|
if ($node instanceof DOMElement) {
|
|
225
|
-
$
|
|
226
|
-
$
|
|
179
|
+
$pushed = false;
|
|
180
|
+
$tag = strtolower($node->nodeName);
|
|
227
181
|
|
|
228
|
-
if ($tag === 'script' && $inBody) {
|
|
229
|
-
|
|
230
|
-
$node->setAttribute('type', 'module');
|
|
231
|
-
}
|
|
182
|
+
if ($tag === 'script' && $inBody && !$node->hasAttribute('src')) {
|
|
183
|
+
$node->setAttribute('type', 'text/php');
|
|
232
184
|
}
|
|
233
185
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
$node->setAttribute($attr->name, $attr->value);
|
|
238
|
-
$node->setAttribute("pp-bind-{$attr->name}", $expr);
|
|
239
|
-
}
|
|
186
|
+
if ($node->hasAttribute('pp-section-id')) {
|
|
187
|
+
self::$sectionStack[] = $node->getAttribute('pp-section-id');
|
|
188
|
+
$pushed = true;
|
|
240
189
|
}
|
|
241
190
|
|
|
242
|
-
$
|
|
243
|
-
$attributes = [];
|
|
244
|
-
foreach ($node->attributes as $attr) {
|
|
245
|
-
$attributes[$attr->name] = $attr->value;
|
|
246
|
-
}
|
|
191
|
+
self::processAttributes($node);
|
|
247
192
|
|
|
248
|
-
if (isset(self::$classMappings[$
|
|
249
|
-
$
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
193
|
+
if (isset(self::$classMappings[$node->nodeName])) {
|
|
194
|
+
$html = self::renderComponent(
|
|
195
|
+
$node,
|
|
196
|
+
$node->nodeName,
|
|
197
|
+
self::getNodeAttributes($node)
|
|
198
|
+
);
|
|
199
|
+
if ($pushed) {
|
|
200
|
+
array_pop(self::$sectionStack);
|
|
253
201
|
}
|
|
254
|
-
|
|
202
|
+
return $html;
|
|
203
|
+
}
|
|
255
204
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
205
|
+
$children = '';
|
|
206
|
+
foreach ($node->childNodes as $c) {
|
|
207
|
+
$children .= self::processNode($c, $inBody || $tag === 'body');
|
|
208
|
+
}
|
|
209
|
+
$attrs = self::getNodeAttributes($node) + ['children' => $children];
|
|
210
|
+
$out = self::renderAsHtml($node->nodeName, $attrs);
|
|
260
211
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
$childOutput = [];
|
|
264
|
-
foreach ($node->childNodes as $child) {
|
|
265
|
-
$childOutput[] = self::processNode($child, $currentInBody);
|
|
266
|
-
}
|
|
267
|
-
$attributes['children'] = implode('', $childOutput);
|
|
268
|
-
return self::renderAsHtml($componentName, $attributes);
|
|
212
|
+
if ($pushed) {
|
|
213
|
+
array_pop(self::$sectionStack);
|
|
269
214
|
}
|
|
215
|
+
return $out;
|
|
270
216
|
}
|
|
271
217
|
|
|
272
218
|
if ($node instanceof DOMComment) {
|
|
@@ -276,93 +222,123 @@ class TemplateCompiler
|
|
|
276
222
|
return $node->textContent;
|
|
277
223
|
}
|
|
278
224
|
|
|
279
|
-
|
|
225
|
+
private static function processTextNode(DOMText $node): string
|
|
280
226
|
{
|
|
281
|
-
|
|
282
|
-
|
|
227
|
+
return preg_replace_callback(
|
|
228
|
+
'/{{\s*(.+?)\s*}}/u',
|
|
229
|
+
fn($m) => self::processBindingExpression(trim($m[1])),
|
|
230
|
+
$node->textContent
|
|
231
|
+
);
|
|
232
|
+
}
|
|
283
233
|
|
|
284
|
-
|
|
285
|
-
|
|
234
|
+
private static function processAttributes(DOMElement $node): void
|
|
235
|
+
{
|
|
236
|
+
foreach ($node->attributes as $a) {
|
|
237
|
+
if (!preg_match('/{{\s*(.+?)\s*}}/u', $a->value, $m)) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
286
240
|
|
|
287
|
-
|
|
288
|
-
|
|
241
|
+
$rawExpr = trim($m[1]);
|
|
242
|
+
$node->setAttribute("pp-bind-{$a->name}", $rawExpr);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private static function processBindingExpression(string $expr): string
|
|
247
|
+
{
|
|
248
|
+
if (preg_match('/^[\w.]+$/u', $expr)) {
|
|
249
|
+
return "<span pp-bind=\"{$expr}\"></span>";
|
|
250
|
+
}
|
|
251
|
+
return "<span pp-bind-expr=\"" . htmlspecialchars($expr, ENT_QUOTES, 'UTF-8') . "\"></span>";
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
protected static function renderComponent(DOMElement $node, string $componentName, array $incomingProps): string
|
|
255
|
+
{
|
|
256
|
+
$mapping = self::selectComponentMapping($componentName);
|
|
257
|
+
$attributes = $incomingProps;
|
|
258
|
+
|
|
259
|
+
$attributes['pp-sync-script'] = 's' . base_convert(sprintf('%u', crc32($mapping['className'])), 10, 36);
|
|
260
|
+
|
|
261
|
+
$instance = self::initializeComponentInstance($mapping, $attributes);
|
|
262
|
+
$html = $instance->render();
|
|
263
|
+
if (strpos($html, '{{') !== false || self::hasComponentTag($html)) {
|
|
264
|
+
$html = self::compile($html);
|
|
289
265
|
}
|
|
290
266
|
|
|
267
|
+
return $html;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private static function selectComponentMapping(string $componentName): array
|
|
271
|
+
{
|
|
272
|
+
if (!isset(self::$classMappings[$componentName])) {
|
|
273
|
+
throw new RuntimeException("Component {$componentName} not registered");
|
|
274
|
+
}
|
|
291
275
|
$mappings = self::$classMappings[$componentName];
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
if ($selectedMapping === null) {
|
|
305
|
-
$selectedMapping = $mappings[0];
|
|
276
|
+
|
|
277
|
+
$srcNorm = str_replace('\\', '/', SRC_PATH) . '/';
|
|
278
|
+
$relImp = str_replace($srcNorm, '', str_replace('\\', '/', Bootstrap::$contentToInclude));
|
|
279
|
+
|
|
280
|
+
if (isset($mappings[0]) && is_array($mappings[0])) {
|
|
281
|
+
foreach ($mappings as $entry) {
|
|
282
|
+
$imp = isset($entry['importer'])
|
|
283
|
+
? str_replace('\\', '/', $entry['importer'])
|
|
284
|
+
: '';
|
|
285
|
+
if (str_replace($srcNorm, '', $imp) === $relImp) {
|
|
286
|
+
return $entry;
|
|
306
287
|
}
|
|
307
|
-
} else {
|
|
308
|
-
$selectedMapping = $mappings;
|
|
309
288
|
}
|
|
289
|
+
return $mappings[0];
|
|
310
290
|
}
|
|
291
|
+
return $mappings;
|
|
292
|
+
}
|
|
311
293
|
|
|
312
|
-
|
|
313
|
-
|
|
294
|
+
protected static function initializeComponentInstance(array $mapping, array $attributes)
|
|
295
|
+
{
|
|
296
|
+
if (!isset($mapping['className'], $mapping['filePath'])) {
|
|
297
|
+
throw new RuntimeException("Invalid mapping");
|
|
314
298
|
}
|
|
315
|
-
|
|
316
|
-
$
|
|
317
|
-
$filePath = $selectedMapping['filePath'];
|
|
299
|
+
$className = $mapping['className'];
|
|
300
|
+
$filePath = $mapping['filePath'];
|
|
318
301
|
|
|
319
302
|
require_once str_replace('\\', '/', SRC_PATH . '/' . $filePath);
|
|
320
|
-
|
|
321
303
|
if (!class_exists($className)) {
|
|
322
|
-
throw new RuntimeException("Class {$className}
|
|
304
|
+
throw new RuntimeException("Class {$className} not found");
|
|
323
305
|
}
|
|
324
306
|
|
|
325
|
-
$attributes['pp-sync-script'] = base64_encode($className);
|
|
326
307
|
return new $className($attributes);
|
|
327
308
|
}
|
|
328
309
|
|
|
329
310
|
protected static function initializeClassMappings(): void
|
|
330
311
|
{
|
|
331
|
-
foreach (PrismaPHPSettings::$classLogFiles as $
|
|
332
|
-
self::$classMappings[$
|
|
312
|
+
foreach (PrismaPHPSettings::$classLogFiles as $tag => $cls) {
|
|
313
|
+
self::$classMappings[$tag] = $cls;
|
|
333
314
|
}
|
|
334
315
|
}
|
|
335
316
|
|
|
336
|
-
protected static function hasComponentTag(string $
|
|
317
|
+
protected static function hasComponentTag(string $html): bool
|
|
337
318
|
{
|
|
338
|
-
return preg_match('/<\/*[A-Z][\w-]*/u', $
|
|
319
|
+
return preg_match('/<\/*[A-Z][\w-]*/u', $html) === 1;
|
|
339
320
|
}
|
|
340
321
|
|
|
341
|
-
|
|
322
|
+
private static function getNodeAttributes(DOMElement $node): array
|
|
342
323
|
{
|
|
343
|
-
$
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
return "<{$tagName}{$attrs} />";
|
|
324
|
+
$out = [];
|
|
325
|
+
foreach ($node->attributes as $a) {
|
|
326
|
+
$out[$a->name] = $a->value;
|
|
347
327
|
}
|
|
348
|
-
|
|
349
|
-
$innerContent = $attributes['children'] ?? '';
|
|
350
|
-
return "<{$tagName}{$attrs}>{$innerContent}</{$tagName}>";
|
|
328
|
+
return $out;
|
|
351
329
|
}
|
|
352
330
|
|
|
353
|
-
|
|
331
|
+
private static function renderAsHtml(string $tag, array $attrs): string
|
|
354
332
|
{
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
$attrArray = [];
|
|
360
|
-
foreach ($attributes as $key => $value) {
|
|
361
|
-
if ($key !== "children") {
|
|
362
|
-
$attrArray[] = "{$key}=\"{$value}\"";
|
|
333
|
+
$pairs = [];
|
|
334
|
+
foreach ($attrs as $k => $v) {
|
|
335
|
+
if ($k !== 'children') {
|
|
336
|
+
$pairs[] = "{$k}=\"{$v}\"";
|
|
363
337
|
}
|
|
364
338
|
}
|
|
365
|
-
|
|
366
|
-
return
|
|
339
|
+
$attrStr = $pairs ? ' ' . implode(' ', $pairs) : '';
|
|
340
|
+
return in_array(strtolower($tag), self::$selfClosingTags)
|
|
341
|
+
? "<{$tag}{$attrStr} />"
|
|
342
|
+
: "<{$tag}{$attrStr}>{$attrs['children']}</{$tag}>";
|
|
367
343
|
}
|
|
368
344
|
}
|
package/dist/src/app/js/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{const e=EventTarget.prototype.addEventListener,t=EventTarget.prototype.removeEventListener,n=new Map;EventTarget.prototype.addEventListener=function(t,s,i){n.has(this)||n.set(this,new Map);const r=n.get(this).get(t)||new Set;r.add(s),n.get(this).set(t,r),e.call(this,t,s,i)},EventTarget.prototype.removeEventListener=function(e,s,i){if(n.has(this)&&n.get(this).has(e)){const t=n.get(this).get(e);t&&(t.delete(s),0===t.size&&n.get(this).delete(e))}t.call(this,e,s,i)},EventTarget.prototype.removeAllEventListeners=function(e){if(n.has(this)&&n.get(this).has(e)){const s=n.get(this).get(e);s&&(s.forEach((n=>{t.call(this,e,n)})),n.get(this).delete(e))}}})();class PPHP{props={};bindings=[];static _instance;isNavigating=!1;responseData=null;activeAbortController=null;rawProps={};state={checkedElements:new Set};reservedWords;pendingBindings=new Set;updateScheduled=!1;templateStore=new WeakMap;_proxyCache=new WeakMap;builtInProps;eventHandlers;redirectRegex=/redirect_7F834\s*=\s*(\/[^\s]*)/;mustacheRe=/\{\{\s*([\s\S]+?)\s*\}\}/gu;assignmentRe=/^\s*[\w.]+\s*=(?!=)/;htmlEntitiesRe=/"|'|&/g;mutators;arrayMethodCache=new WeakMap;static PATH_PATTERN=/\b([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\b/g;static MUSTACHE_TEST=/\{\{\s*[\s\S]+?\s*\}\}/;static MUSTACHE_PATTERN=/\{\{\s*([\s\S]+?)\s*\}\}/g;constructor(){const e=Object.getOwnPropertyNames(HTMLElement.prototype).filter((e=>e.startsWith("on"))),t=Object.getOwnPropertyNames(Document.prototype).filter((e=>e.startsWith("on"))),n=Object.getOwnPropertyNames(Window.prototype).filter((e=>e.startsWith("on")));this.eventHandlers=new Set([...e,...t,...n].map((e=>e.toLowerCase()))),this.builtInProps=new Set(["length","charAt","charCodeAt","codePointAt","concat","includes","endsWith","indexOf","lastIndexOf","localeCompare","match","matchAll","normalize","padEnd","padStart","repeat","replace","replaceAll","search","slice","split","substring","substr","startsWith","toLocaleLowerCase","toLocaleUpperCase","toLowerCase","toString","toUpperCase","trim","trimEnd","trimStart","valueOf"]),this.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"]),this.mutators=new Set(["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"]),this.handlePopState(),this.props=this.makeReactive(this.rawProps)}static get instance(){return PPHP._instance||(PPHP._instance=new PPHP),PPHP._instance}extractDependencies(e){const t=e.replace(/\?\./g,".");return new Set(t.match(/\b[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\b/g)||[])}formatValue(e){return"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,n="text",s){if(this.assignmentRe.test(t))return;const i=new Set([...this.extractDependencies(t)].map((e=>e.split(".")[0])).filter((e=>e in this.props&&!this.reservedWords.has(e)))),r=this.makeSafeEvaluator(t);if("value"===s||"checked"===s){const t=this.makePrimitiveUpdater(e,s,r);return void this.bindings.push({dependencies:i,update:t})}if(s){const n=e.getAttribute(s)??"";if(this.mustacheRe.test(t)||this.mustacheRe.test(n)){const r=this.mustacheRe.test(t)?t:n,a=this.makeAttrTemplateUpdater(e,s,i,r);return void this.bindings.push({dependencies:i,update:a})}const a=()=>{try{const t=r(this.props),n=this.formatValue(t);s in e&&(e[s]=n),e.setAttribute(s,n)}catch(e){console.error(`Error evaluating the attribute "${s}" with expression "${t}". Please ensure the expression is valid.`,e)}};return void this.bindings.push({dependencies:i,update:a})}const a={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:i,update:()=>{try{const t=r(this.props),s=this.formatValue(t);a[n](e,s)}catch(e){console.error(`Error evaluating the expression: "${t}". Please check the syntax and ensure all variables are defined.`,e)}}})}makePrimitiveUpdater(e,t,n){return()=>{try{const s=n(this.props),i=this.formatValue(s);"value"===t?"value"in e&&e.value!==i?e.value=i:e.setAttribute("value",i):"checked"in e?e.checked="true"===i:e.setAttribute("checked",i)}catch(e){console.error(`Error evaluating the attribute "${t}". Please ensure the expression is valid.`,e)}}}makeAttrTemplateUpdater(e,t,n,s){let i=this.templateStore.get(e);i||(i=new Map,this.templateStore.set(e,i)),i.has(t)||i.set(t,e.getAttribute(t)||"");const r=s??i.get(t)??"";return(r.match(this.mustacheRe)||[]).forEach((e=>{this.extractDependencies(e).forEach((e=>n.add(e)))})),()=>{try{const n=r.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)!==n&&e.setAttribute(t,n)}catch(e){console.error(`Error evaluating the template for attribute "${t}". Please check the template syntax and dependencies.`,e)}}}initBindings(){this.bindings=[],document.body.querySelectorAll("*").forEach((e=>{["pp-bind","pp-bind-expr"].forEach((t=>{const n=e.getAttribute(t);n&&this.registerBinding(e,n,"text")})),Array.from(e.attributes).forEach((t=>{if(!t.name.startsWith("pp-bind-"))return;const n=t.value.replace(this.htmlEntitiesRe,(e=>"""===e?'"':"'"===e?"'":"&")).replace(/^{{\s*|\s*}}$/g,"");let s=t.name.replace(/^(pp-bind-)+/,"");const i=s.toLowerCase();"html"!==i&&"innerhtml"!==i||(s="innerHTML");const r="value"===s?"value":"checked"===s?"checked":"text";this.registerBinding(e,n,r,s)}))}))}safeNull=new Proxy({},{get:(e,t)=>t===Symbol.toPrimitive?()=>{}:this.builtInProps.has(t.toString())?()=>"":this.safeNull,apply:()=>""});safeTag=(e,...t)=>e.reduce(((e,n,s)=>{const i=t[s];return e+n+(null==i||"object"==typeof i?"":i)}),"");makeSafeEvaluator(e){let t=e.trim();const n=t.replace(/\?\./g,".");if(/^\(\s*\)\s*=>/.test(t)&&(t=`(${t})()`),t.startsWith("`")&&t.endsWith("`")){const e=t.slice(1,-1),n=/\$\{\s*([^}]+?)\s*\}/g,s=new Set;let i;for(;i=n.exec(e);){const e=i[1];this.extractDependencies(e).forEach((e=>s.add(e)))}const r=Array.from(s),a=new Function(...r,"safeTag",`return safeTag\`${e}\``);return e=>{const t=r.map((t=>void 0===e[t]?this.safeNull:e[t]));return a(...t,this.safeTag.bind(this))}}const s=n.replace(/(["'])(?:(?=(\\?))\2.)*?\1/g,"").match(/\b[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\b/g)||[],i=new Set(s.map((e=>e.split(".")[0])).filter((e=>!this.reservedWords.has(e)&&"safeTag"!==e))),r=Array.from(i).map((e=>`\n const ${e} = ctx["${e}"] !== undefined \n ? ctx["${e}"] \n : (typeof window !== "undefined" && window["${e}"] !== undefined \n ? window["${e}"] \n : ${new RegExp(`\\b${e}\\.`).test(n)?"{}":"void 0"});\n if (typeof window !== "undefined" && window["${e}"] !== ${e}) {\n window["${e}"] = ${e};\n }\n `)).join("\n"),a=/^\s*[\w\.]+\s*=(?!=)/.test(t),o=new Function("ctx","safeTag",`\n "use strict";\n ${r}\n try {\n ${a?t+"; return '';":"const result = "+t+"; return result === undefined || result === null ? '' : result;"}\n } catch (e) {\n return "";\n }\n `);return e=>o(e,this.safeTag.bind(this))}setNestedProperty(e,t,n){const s=t.split(".");let i=e;for(let e=0;e<s.length-1;e++)s[e]in i||(i[s[e]]={}),i=i[s[e]];i[s[s.length-1]]=n}resetProps(){Object.keys(this.rawProps).forEach((e=>{window.hasOwnProperty(e)&&delete window[e]})),this.rawProps={},this.bindings=[],this.props=this.makeReactive(this.rawProps)}initializeAllReferencedProps(){const e=PPHP.PATH_PATTERN,t=PPHP.MUSTACHE_PATTERN,n=PPHP.MUSTACHE_TEST,s=this.props,i=this.builtInProps,r=new Set,a=document.body.getElementsByTagName("*");for(let s=0,o=a.length;s<o;s++){const o=a[s].attributes;for(let s=0,a=o.length;s<a;s++){const{name:a,value:c}=o[s];if(c&&n.test(c))for(const n of c.matchAll(t)){const t=n[1];for(const n of t.matchAll(e)){const e=n[1],t=e.split(".")[0];i.has(t)||r.add(e)}}if(a.startsWith("pp-bind"))for(const t of c.matchAll(e)){const e=t[1],n=e.split(".")[0];i.has(n)||r.add(e)}}}const o=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT,{acceptNode:e=>n.test(e.nodeValue||"")?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT});let c;for(;c=o.nextNode();){const n=c.nodeValue;for(const s of n.matchAll(t)){const t=s[1];for(const n of t.matchAll(e)){const e=n[1],t=e.split(".")[0];i.has(t)||r.add(e)}}}for(const e of r){const t=e.split(".");let n=s;for(let e=0;e<t.length;e++){const s=t[e];if(i.has(s)||null==n||"object"!=typeof n)break;s in n||(n[s]=e===t.length-1?void 0:{}),n=n[s]}}const l=new Set;for(const e of r)l.add(e.split(".")[0]);l.forEach((e=>{e in globalThis||Object.defineProperty(globalThis,e,{configurable:!0,enumerable:!0,get:()=>s[e],set:t=>{s[e]=t}})}))}scheduleBindingUpdate(e){this.pendingBindings.add(e),this.updateScheduled||(this.updateScheduled=!0,requestAnimationFrame((()=>{this.flushBindings()})))}flushBindings(){this.pendingBindings.forEach((e=>{e.update()})),this.pendingBindings.clear(),this.updateScheduled=!1}initMakeReactive(){this.templateStore=new WeakMap,this.initializeAllReferencedProps(),this.initBindings(),this.initLoopBindings(),this.bindings.forEach((e=>e.update()))}getProxiedProps(e){let t=this._proxyCache.get(e);if(t)return t;return t=new Proxy(e,{get:(e,t)=>t in e?e[t]:void 0,set:(e,t,n)=>(e[t]=n,!0)}),this._proxyCache.set(e,t),t}async invokeHandler(e,t,n){try{const s=t.trim(),i=s.replace(/(["'`])(?:\\.|(?!\1).)*\1/g,"").replace(/\/(?:\\.|[^\/])+\/[gimsuy]*/g,"");if(/^\(?\s*[^=]*?\)?\s*=>/.test(i.trim())){const t=new Function("event","proxy","props",`\n with (proxy) {\n const val = (${s});\n return (typeof val === "function")\n ? val.call(this, event, props)\n : val;\n }\n `),i=this.getProxiedProps(pphp.props);return void await t.call(e,n,i,pphp.props)}const r=t.match(/^(\w+(\.\w+)*)\((.*)\)$/);if(r){const s=r[1],i=r[3],a=s.split("."),{context:o,methodName:c}=this.resolveContext(a);if("function"==typeof o[c])if(this.isJsonLike(i)){const t=this.parseJson(i);t.element=e,t.event=n;const s=[t];await o[c](...s)}else new Function("event",t).call(e,n);else await this.handleParsedCallback(e,t)}else if(t.includes("=")){const s=t.match(/^\s*([\w\.]+)\s*=/);if(s){const e=s[1];if(e.includes(".")){const t=e.split(".");let n=pphp.props;for(let e=0;e<t.length-1;e++)t[e]in n||(n[t[e]]={}),n=n[t[e]]}else e in pphp.props||(pphp.props[e]=void 0)}new Function("event","props",`\n with (new Proxy(props, {\n get(target, key) {\n return key in target ? target[key] : undefined;\n },\n set(target, key, value) {\n target[key] = value;\n return true;\n }\n })) {\n ${t}\n }\n `).call(e,n,pphp.props)}else await this.handleParsedCallback(e,t)}catch(e){console.error(`Error executing handler "${t}". Please ensure the handler is defined and valid.`,e)}}registerLoop(e){const t=e.getAttribute("pp-for").trim(),[n,s]=t.split(/\s+in\s+/),[i,r]=n.replace(/^\(|\)$/g,"").split(",").map((e=>e.trim())),a=e.parentNode,o=document.createComment("pp-for");a.insertBefore(o,e),a.removeChild(e);const c=this.makeSafeEvaluator(s),l=this.extractDependencies(s);this.bindings.push({dependencies:l,update:()=>{let t=o.nextSibling;for(;t&&t.nodeType!==Node.COMMENT_NODE;){const e=t.nextSibling;a.removeChild(t),t=e}(c(this.props)||[]).forEach(((t,n)=>{this.props[i]=t,r&&(this.props[r]=n);const s=e.content.cloneNode(!0);s.querySelectorAll("[pp-bind]").forEach((e=>{const t=e.getAttribute("pp-bind"),n=this.makeSafeEvaluator(t)(this.props);e.textContent=this.formatValue(n)})),s.querySelectorAll("*").forEach((e=>{Array.from(e.attributes).forEach((t=>{if(t.name.startsWith("on")&&/\bi\b/.test(t.value)){const s=t.value.replace(/\bi\b/g,String(n));e.setAttribute(t.name,s)}}))})),a.insertBefore(s,o.nextSibling)})),this.attachWireFunctionEvents()}})}initLoopBindings(){document.querySelectorAll("[pp-for]").forEach((e=>this.registerLoop(e)))}makeReactive(e,t=[]){const n=this._proxyCache.get(e);if(n)return n;const s=this;if(e instanceof Map||e instanceof Set)return e;const i=new Proxy(e,{get(e,n,i){const r=Reflect.get(e,n,i);if(Array.isArray(e)&&s.mutators.has(n)){let a=s.arrayMethodCache.get(e);if(a||(a=new Map,s.arrayMethodCache.set(e,a)),!a.has(n)){const e=r,o=t.join("."),c=function(...t){const n=Reflect.apply(e,i,t);return queueMicrotask((()=>{s.bindings.forEach((e=>{e.dependencies.has(o)&&s.scheduleBindingUpdate(e)}))})),n};a.set(n,c)}return a.get(n)}return"object"==typeof r&&null!==r?s.makeReactive(r,[...t,n]):r},set(e,n,i){i&&"object"==typeof i&&(i=s.makeReactive(i,[...t,n.toString()])),e[n]=i;const r=[...t,n].join(".");return s.bindings.forEach((e=>{for(const t of e.dependencies)if(r===t||r.startsWith(t+".")||t.startsWith(r+".")){s.scheduleBindingUpdate(e);break}})),!0}});return this._proxyCache.set(e,i),i}handlePopState(){window.addEventListener("popstate",(async()=>{await this.handleNavigation()}))}attachWireFunctionEvents(){this.handleHiddenAttribute(),this.handleAnchorTag();const e=Array.from(this.eventHandlers).map((e=>`[${e}]`)).join(", ");document.body.querySelectorAll(e).forEach((e=>{if(Array.from(e.attributes).filter((e=>this.eventHandlers.has(e.name))).forEach((t=>{const n=t.name.slice(2),s=t.value;e instanceof HTMLInputElement&&this.handleInputAppendParams(e,n),s&&(e.removeAttribute(t.name),this.handleDebounce(e,n,s))})),e instanceof HTMLFormElement){const t=e.getAttribute("onsubmit");t&&(e.removeAttribute("onsubmit"),this.handleDebounce(e,"submit",t))}}))}async handleDebounce(e,t,n){e.removeEventListener(t,(()=>{}));const s=e.getAttribute("pp-debounce")||"",i=e.getAttribute("pp-before-request")||"",r=e.getAttribute("pp-after-request")||"",a=async t=>{t.preventDefault();try{i&&await this.invokeHandler(e,i,t),await this.invokeHandler(e,n,t),r&&"@close"!==r&&await this.invokeHandler(e,r,t),this.handlerAutofocusAttribute()}catch(e){console.error("Error in debounced handler. Please check the handler logic and ensure it is functioning correctly.",e)}};if(s){const n=this.parseTime(s),i=this.debounce(a,n);e instanceof HTMLFormElement&&"submit"===t?e.addEventListener(t,(e=>{e.preventDefault(),i(e)})):e.addEventListener(t,i)}else e.addEventListener(t,a)}debounce(e,t=300,n=!1){let s;return function(...i){const r=this;s&&clearTimeout(s),s=setTimeout((()=>{s=null,n||e.apply(r,i)}),t),n&&!s&&e.apply(r,i)}}handlerAutofocusAttribute(){const e=document.activeElement;if(e&&e!==document.body)return;const t=this.state?.focusId;if(!t)return;const n=document.querySelectorAll("[pp-autofocus]");let s=!1;n.forEach((e=>{if(s)return;const t=e.getAttribute("pp-autofocus");if(!t||!this.isJsonLike(t))return;const n=this.parseJson(t);if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e instanceof HTMLInputElement)if(["text","search","tel","url","password"].includes(e.type))if("number"===e.type){e.type="text";const t=e.value.length||0;e.setSelectionRange(t,t),e.type="number"}else this.setCursorPosition(e,n);else;else e instanceof HTMLTextAreaElement&&this.setCursorPosition(e,n)}e.focus(),s=!0}))}async handleParsedCallback(e,t){const{funcName:n,data:s}=this.parseCallback(e,t);if(!n)return;const i=this[n],r=window[n];let a;if("function"==typeof i?a=i:"function"==typeof r&&(a=r),"function"==typeof a){const t=e.hasAttribute("pp-after-request"),n=Array.isArray(s.args)?s.args:[],i=this.responseData?this.parseJson(this.responseData):{response:this.responseData};let r={args:n,element:e,data:s};t&&(r={...r,...i}),await a.call(this,r)}else this.responseData=null,this.responseData=await this.handleUndefinedFunction(e,n,s)}async handleUndefinedFunction(e,t,n){const s={callback:t,...n},i=this.createFetchOptions(s),r=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});try{this.saveElementOriginalState(e),this.handleSuspenseElement(e);const s=new URL(window.location.href);let a="",o="",c={success:!1};const l=e.querySelector("input[type='file']");if(l){if(a=await this.fetchFileWithData(s.href,t,l,n),o=this.extractJson(a)||"",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(s.href,i);if(a=await e.text(),this.getRedirectUrl(a))return void await this.redirect(this.getRedirectUrl(a)||"");if(o=this.extractJson(a)||"",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")||"",d=e.getAttribute("pp-after-request")||"";if((h||d&&c.success)&&this.restoreSuspenseElement(e),h||d){let e="";if(c.success){e=a.replace(o,"")}else e=a;if(this.appendAfterbegin(e),!d&&!c.success)return}if(d&&c.success){this.handleAfterRequest(d,o);const e=a.replace(o,"");return this.appendAfterbegin(e),o}if("@close"===d)return c.success?o:void 0;const u=await this.fetch(s.href,r),p=await u.text();if(this.getRedirectUrl(p))return void await this.redirect(this.getRedirectUrl(p)||"");await this.handleResponseRedirectOrUpdate(a,p,o,c)}catch(e){console.error(`Error handling undefined function "${t}". Please ensure the function is defined and accessible.`,e)}}handleAfterRequest(e,t){if(!this.isJsonLike(e))return;const n=this.parseJson(e),s=t?this.parseJson(t):null,i=n.targets;Array.isArray(i)&&i.forEach((e=>{const{id:t,...n}=e,i=document.querySelector(t);let r={};if(s){for(const t in n)if(n.hasOwnProperty(t))switch(t){case"innerHTML":case"outerHTML":case"textContent":case"innerText":"response"===n[t]&&(r[t]=e.responseKey?s[e.responseKey]:s.response);break;default:r[t]=n[t]}}else r=n;i&&this.updateElementAttributes(i,r)}))}async handleResponseRedirectOrUpdate(e,t,n,s){const i=this.getUpdatedHTMLContent(e,n,s),r=(new DOMParser).parseFromString(t,"text/html");i&&r.body.insertAdjacentElement("afterbegin",i),this.updateBodyContent(r.body.outerHTML)}getUpdatedHTMLContent(e,t,n){const s=document.createElement("div");if(s.id="afterbegin-8D95D",n&&t?.success){const t=e.replace(n,"");s.innerHTML=t}else s.innerHTML=e;return s.innerHTML?s:null}async updateBodyContent(e){const t=this.saveScrollPositions();this.saveState();const n=(new DOMParser).parseFromString(e,"text/html");await this.appendCallbackResponse(n),this.restoreState(),this.restoreScrollPositions(t),this.resetProps(),this.initMakeReactive(),this.attachWireFunctionEvents(),this.processInlineModuleScripts(),requestAnimationFrame((()=>{document.body.classList.add("pp-hydrated")}))}restoreState(){if(this.state.focusId){const e=document.getElementById(this.state.focusId)||document.querySelector(`[name="${this.state.focusId}"]`);if(e instanceof HTMLInputElement){const t=e.value.length||0;void 0!==this.state.focusSelectionStart&&null!==this.state.focusSelectionEnd&&e.setSelectionRange(t,t),this.state.focusValue&&("checkbox"===e.type||"radio"===e.type?e.checked=!!this.state.focusChecked:"number"===e.type||"email"===e.type?(e.type="text",e.setSelectionRange(t,t),e.type="number"===e.type?"number":"email"):"date"===e.type||"month"===e.type||"week"===e.type||"time"===e.type||"datetime-local"===e.type||"color"===e.type||"file"===e.type||""!==e.value&&(e.value=this.state.focusValue)),e.focus()}else if(e instanceof HTMLTextAreaElement){const t=e.value.length||0;void 0!==this.state.focusSelectionStart&&null!==this.state.focusSelectionEnd&&e.setSelectionRange(t,t),this.state.focusValue&&""!==e.value&&(e.value=this.state.focusValue),e.focus()}else e instanceof HTMLSelectElement&&(this.state.focusValue&&""!==e.value&&(e.value=this.state.focusValue),e.focus())}this.state.checkedElements.forEach((e=>{const t=document.getElementById(e);t&&(t.checked=!0)}))}async appendCallbackResponse(e){const t=e.getElementById("afterbegin-8D95D");if(t){const e=document.getElementById("afterbegin-8D95D");e?e.innerHTML=t.innerHTML:document.body.insertAdjacentHTML("afterbegin",t.outerHTML)}await this.populateDocumentBody(e)}saveState(){const e=document.activeElement;this.state.focusId=e?.id||e?.name,this.state.focusValue=e?.value,this.state.focusChecked=e?.checked,this.state.focusType=e?.type,this.state.focusSelectionStart=e?.selectionStart,this.state.focusSelectionEnd=e?.selectionEnd,this.state.isSuspense=e.hasAttribute("pp-suspense"),this.state.checkedElements.clear(),document.querySelectorAll('input[type="checkbox"]:checked').forEach((e=>{this.state.checkedElements.add(e.id||e.name)})),document.querySelectorAll('input[type="radio"]:checked').forEach((e=>{this.state.checkedElements.add(e.id||e.name)}))}updateElementAttributes(e,t){for(const n in t)if(t.hasOwnProperty(n))switch(n){case"innerHTML":case"outerHTML":case"textContent":case"innerText":e[n]=this.decodeHTML(t[n]);break;case"insertAdjacentHTML":e.insertAdjacentHTML(t.position||"beforeend",this.decodeHTML(t[n].html));break;case"insertAdjacentText":e.insertAdjacentText(t.position||"beforeend",this.decodeHTML(t[n].text));break;case"setAttribute":e.setAttribute(t.attrName,this.decodeHTML(t[n]));break;case"removeAttribute":e.removeAttribute(t[n]);break;case"className":e.className=this.decodeHTML(t[n]);break;case"classList.add":e.classList.add(...this.decodeHTML(t[n]).split(","));break;case"classList.remove":e.classList.remove(...this.decodeHTML(t[n]).split(","));break;case"classList.toggle":e.classList.toggle(this.decodeHTML(t[n]));break;case"classList.replace":const[s,i]=this.decodeHTML(t[n]).split(",");e.classList.replace(s,i);break;case"dataset":e.dataset[t.attrName]=this.decodeHTML(t[n]);break;case"style":Object.assign(e.style,t[n]);break;case"value":e.value=this.decodeHTML(t[n]);break;case"checked":e.checked=t[n];break;default:e.setAttribute(n,this.decodeHTML(t[n]))}}decodeHTML(e){const t=document.createElement("textarea");return t.innerHTML=e,t.value}appendAfterbegin(e){if(!e)return;const t="afterbegin-8D95D";let n=document.getElementById(t);n?(n.innerHTML=e,document.body.insertAdjacentElement("afterbegin",n)):(n=document.createElement("div"),n.id=t,n.innerHTML=e,document.body.insertAdjacentElement("afterbegin",n))}restoreSuspenseElement(e){const t=e.getAttribute("pp-original-state");if(e.hasAttribute("pp-suspense")&&t){const n=(e,t)=>{for(const n in t)t.hasOwnProperty(n)&&("textContent"===n?e.textContent=t[n]:"innerHTML"===n?e.innerHTML=t[n]:"disabled"===n?!0===t[n]?e.setAttribute("disabled","true"):e.removeAttribute("disabled"):e.setAttribute(n,t[n]));for(const n of Array.from(e.attributes))t.hasOwnProperty(n.name)||e.removeAttribute(n.name)},s=(e,t)=>{for(const s in t)if(t.hasOwnProperty(s))for(const t of Array.from(e.elements))if(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement){const e=t.getAttribute("pp-original-state")||"";if(e){if(this.isJsonLike(e)){const s=this.parseJson(e);n(t,s)}else i(t,e);t.removeAttribute("pp-original-state")}}},i=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},r=(e,t)=>{e instanceof HTMLFormElement?s(e,t):n(e,t)};try{const i=this.parseJson(t);if(i)if(e instanceof HTMLFormElement){const t=e.id;if(t){const e=document.querySelector(`[form="${t}"]`);if(e){const t=e.getAttribute("pp-original-state");if(t&&this.isJsonLike(t)){const s=this.parseJson(t);n(e,s)}}}const i=new FormData(e),r={};if(i.forEach(((e,t)=>{r[t]=e})),s(e,r),e.hasAttribute("pp-suspense")){const t=e.getAttribute("pp-suspense")||"";if(this.parseJson(t).disabled)for(const t of Array.from(e.elements))(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&t.removeAttribute("disabled")}}else if(i.targets){i.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&r(s,n)}));const{targets:t,...s}=i;n(e,s)}else{const{empty:t,...s}=i;n(e,s)}}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,n,s={}){const i=new FormData,r=n.files;if(r)for(let e=0;e<r.length;e++)i.append("file[]",r[e]);i.append("callback",t);for(const e in s)s.hasOwnProperty(e)&&i.append(e,s[e]);const a=await this.fetch(e,{method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:i});return await a.text()}async handleSuspenseElement(e){let t=e.getAttribute("pp-suspense")||"";const n=(e,t)=>{for(const n in t)if(t.hasOwnProperty(n))for(const t of e.elements)if(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement){const e=t.getAttribute("pp-suspense")||"";if(e)if(this.isJsonLike(e)){const n=this.parseJson(e);"disabled"!==n.onsubmit&&this.updateElementAttributes(t,n),n.targets&&n.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&i(s,n)}))}else s(t,e)}},s=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},i=(e,t)=>{e instanceof HTMLFormElement?n(e,t):this.updateElementAttributes(e,t)};try{if(t&&this.isJsonLike(t)){const s=this.parseJson(t);if(s)if(e instanceof HTMLFormElement){const t=new FormData(e),i={};t.forEach(((e,t)=>{i[t]=e})),s.disabled&&this.toggleFormElements(e,!0);const{disabled:r,...a}=s;this.updateElementAttributes(e,a),n(e,i)}else if(s.targets){s.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&i(s,n)}));const{targets:t,...n}=s;this.updateElementAttributes(e,n)}else{if("disabled"===s.empty&&""===e.value)return;const{empty:t,...n}=s;this.updateElementAttributes(e,n)}}else if(t)s(e,t);else if(e instanceof HTMLFormElement){const t=new FormData(e),s={};t.forEach(((e,t)=>{s[t]=e})),n(e,s)}}catch(e){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 n=0;n<e.attributes.length;n++){const s=e.attributes[n];t[s.name]=s.value}e.setAttribute("pp-original-state",JSON.stringify(t))}if(e instanceof HTMLFormElement){let t=null;const n=e.id;n&&(t=document.querySelector(`[form="${n}"]`)),n&&t||(t=Array.from(e.elements).find((e=>e instanceof HTMLButtonElement||e instanceof HTMLInputElement))),t?t.hasAttribute("pp-original-state")||this.saveElementOriginalState(t):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,n)=>{e[n]=t})),e}createFetchOptions(e){return{method:"POST",headers:{"Content-Type":"application/json",HTTP_PPHP_WIRE_REQUEST:"true"},body:JSON.stringify(e)}}parseCallback(e,t){let n={};const s=e.closest("form");if(s){new FormData(s).forEach(((e,t)=>{n[t]?Array.isArray(n[t])?n[t].push(e):n[t]=[n[t],e]:n[t]=e}))}else e instanceof HTMLInputElement?n=this.handleInputElement(e):(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(n[e.name]=e.value);const i=t.match(/(\w+)\((.*)\)/);if(i){const e=i[1];let t=i[2].trim();if(t.startsWith("{")&&t.endsWith("}"))try{const e=this.parseJson(t);"object"==typeof e&&null!==e&&(n={...n,...e})}catch(e){console.error(`Error parsing JSON: ${e instanceof Error?e.message:"Unknown error"}. Please ensure the JSON string is valid.`,e)}else{const e=t.split(/,(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/).map((e=>e.trim().replace(/^['"]|['"]$/g,"")));n.args=e}return{funcName:e,data:n}}return{funcName:t,data:n}}handleInputElement(e){let t={};if(e.name)if("checkbox"===e.type)t[e.name]={value:e.value,checked:e.checked};else if("radio"===e.type){const n=document.querySelector(`input[name="${e.name}"]:checked`);t[e.name]=n?n.value:null}else t[e.name]=e.value;else"checkbox"===e.type||"radio"===e.type?t.value=e.checked:t.value=e.value;return t}resolveContext(e){let t=window;for(let n=0;n<e.length-1;n++)if(t=t[e[n]],!t)throw new Error(`Cannot find object ${e[n]} in the context.`);return{context:t,methodName:e[e.length-1]}}setCursorPosition(e,t){if(t.start)e.setSelectionRange(0,0);else if(t.end){const t=e.value.length||0;e.setSelectionRange(t,t)}else if(t.length){const n=parseInt(t.length,10)||0;e.setSelectionRange(n,n)}}handleInputAppendParams(e,t){const n=e.getAttribute("pp-append-params"),s=e.getAttribute("pp-append-params-sync");if("true"===n){if("true"===s){const t=e.name||e.id;if(t){const n=new URL(window.location.href),s=new URLSearchParams(n.search);s.has(t)&&(e.value=s.get(t)||"")}}e.addEventListener(t,(e=>{const t=e.currentTarget,n=t.value,s=new URL(window.location.href),i=new URLSearchParams(s.search),r=t.name||t.id;if(r){n?i.set(r,n):i.delete(r);const e=i.toString()?`${s.pathname}?${i.toString()}`:s.pathname;history.replaceState(null,"",e)}}))}}handleHiddenAttribute(){const e=document.querySelectorAll("[pp-visibility]"),t=document.querySelectorAll("[pp-display]"),n=this.handleElementVisibility.bind(this),s=this.handleElementDisplay.bind(this);e.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-visibility",n))),t.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-display",s)))}handleVisibilityElementAttribute(e,t,n){const s=e.getAttribute(t);if(s)if(this.isJsonLike(s)){n(e,this.parseJson(s))}else{const n=this.parseTime(s);if(n>0){const s="pp-visibility"===t?"visibility":"display",i="visibility"===s?"hidden":"none";this.scheduleChange(e,n,s,i)}}}handleElementVisibility(e,t){this.handleElementChange(e,t,"visibility","hidden","visible")}handleElementDisplay(e,t){this.handleElementChange(e,t,"display","none","block")}handleElementChange(e,t,n,s,i){const r=t.start?this.parseTime(t.start):0,a=t.end?this.parseTime(t.end):0;r>0?(e.style[n]=s,this.scheduleChange(e,r,n,i),a>0&&this.scheduleChange(e,r+a,n,s)):a>0&&this.scheduleChange(e,a,n,s)}handleAnchorTag(){document.querySelectorAll("a").forEach((e=>{e.addEventListener("click",(async e=>{const t=e.currentTarget,n=t.getAttribute("href"),s=t.getAttribute("target");if(n&&"_blank"!==s&&!e.metaKey&&!e.ctrlKey&&(e.preventDefault(),!this.isNavigating)){this.isNavigating=!0;try{if(/^(https?:)?\/\//i.test(n)&&!n.startsWith(window.location.origin))window.location.href=n;else{const e=t.getAttribute("pp-append-params");if(n.startsWith("?")&&"true"===e){const e=new URL(window.location.href),t=new URLSearchParams(e.search);let s="";const[i,r]=n.split("#");r&&(s=`#${r}`);new URLSearchParams(i.split("?")[1]).forEach(((e,n)=>{t.set(n,e)}));const a=`${e.pathname}?${t.toString()}${s}`;history.pushState(null,"",a)}else{const[e,t]=n.split("#"),s=`${e}${t?`#${t}`:""}`;history.pushState(null,"",s)}const s=n.indexOf("#");if(-1!==s){const e=n.slice(s+1),t=document.getElementById(e);if(t)t.scrollIntoView({behavior:"smooth"});else{await this.handleNavigation();const t=document.getElementById(e);t&&t.scrollIntoView({behavior:"smooth"})}}else await this.handleNavigation()}}catch(e){console.error("Anchor click error:",e)}finally{this.isNavigating=!1}}}))}))}async handleNavigation(){try{const e=document.getElementById("loading-file-1B87E");if(e){const t=this.findLoadingElement(e,window.location.pathname);t&&await this.updateContentWithTransition(t)}const t=await this.fetch(window.location.href);if(!t.ok)return void console.error(`Navigation error: ${t.status} ${t.statusText}`);const n=await t.text(),s=n.match(this.redirectRegex);if(s&&s[1])return void await this.redirect(s[1]);await this.updateDocumentContent(n)}catch(e){console.error("Navigation error:",e)}}findLoadingElement(e,t){let n=t;for(;;){const t=e.querySelector(`div[pp-loading-url='${n}']`);if(t)return t;if("/"===n)break;const s=n.lastIndexOf("/");n=s<=0?"/":n.substring(0,s)}return e.querySelector("div[pp-loading-url='/' ]")}async updateContentWithTransition(e){const t=document.querySelector("[pp-loading-content='true']")||document.body;if(!t)return;const{fadeIn:n,fadeOut:s}=this.parseTransition(e);await this.fadeOut(t,s),t.innerHTML=e.innerHTML,this.fadeIn(t,n)}parseTransition(e){let t=250,n=250;const s=e.querySelector("[pp-loading-transition]"),i=s?.getAttribute("pp-loading-transition");if(i)try{const e=this.parseJson(i);t=this.parseTime(e.fadeIn??t),n=this.parseTime(e.fadeOut??n)}catch(e){console.error("Failed to parse pp-loading-transition attribute:",e)}return{fadeIn:t,fadeOut:n}}fadeOut(e,t){return new Promise((n=>{e.style.transition=`opacity ${t}ms ease-out`,e.style.opacity="0",setTimeout((()=>{e.style.transition="",n()}),t)}))}fadeIn(e,t){e.style.transition=`opacity ${t}ms ease-in`,e.style.opacity="1",setTimeout((()=>{e.style.transition=""}),t)}async updateDocumentContent(e){const t=this.saveScrollPositions(),n=(new DOMParser).parseFromString(e,"text/html"),s="pp-dynamic-script",i="pp-dynamic-link";document.head.querySelectorAll("[pp-dynamic-meta]").forEach((e=>e.remove()));document.head.querySelectorAll(`[${i}]`).forEach((e=>e.remove()));document.head.querySelectorAll(`[${s}]`).forEach((e=>e.remove()));await(async e=>{Array.from(e.head.children).forEach((e=>{const t=e.tagName;if("SCRIPT"===t&&e.hasAttribute(s)){const t=document.createElement("script");Array.from(e.attributes).forEach((e=>t.setAttribute(e.name,e.value))),e.textContent&&(t.textContent=e.textContent),document.head.appendChild(t)}else if("META"===t){if(e.getAttribute("charset")||"viewport"===e.getAttribute("name"))return;const t=e.name,n=e.getAttribute("property"),s=document.head.querySelector(t?`meta[name="${t}"]`:`meta[property="${n}"]`),i=document.head.querySelector("title");s?document.head.replaceChild(e.cloneNode(!0),s):i?.nextSibling?document.head.insertBefore(e.cloneNode(!0),i.nextSibling):document.head.appendChild(e.cloneNode(!0))}else if("TITLE"===t){const t=document.head.querySelector("title");t?document.head.replaceChild(e.cloneNode(!0),t):document.head.appendChild(e.cloneNode(!0))}else if("LINK"===t){const t=t=>{const n=document.head.querySelector('link[rel="icon"]');if(n)document.head.replaceChild(e.cloneNode(!0),n);else{const e=document.createElement("link");e.rel="icon",e.href=t,document.head.appendChild(e)}};if("icon"===e.getAttribute("rel")){t(e.href)}else if(e.hasAttribute(i)){const t=e.cloneNode(!0);document.head.appendChild(t)}}})),await this.populateDocumentBody(e)})(n),this.restoreScrollPositions(t),this.resetProps(),this.initMakeReactive(),this.attachWireFunctionEvents(),this.processInlineModuleScripts(),requestAnimationFrame((()=>{document.body.classList.add("pp-hydrated")}))}restoreScrollPositions(e){requestAnimationFrame((()=>{const t=e.window;t&&window.scrollTo(t.scrollLeft,t.scrollTop),document.querySelectorAll("*").forEach((t=>{const n=this.getElementKey(t);e[n]&&(t.scrollTop=e[n].scrollTop,t.scrollLeft=e[n].scrollLeft)}))}))}async populateDocumentBody(e){try{const t=e.body.cloneNode(!0);this.manageScriptTags(t),document.body.replaceWith(t)}catch(e){console.error("Error populating document body:",e)}}manageScriptTags(e,t){const n=e.querySelectorAll("script"),s=t?.querySelectorAll("script")||n;n.forEach(((e,t)=>{const n=document.createElement("script"),i=s[t]||e;Array.from(i.attributes).forEach((e=>{n.setAttribute(e.name,e.value)})),i.hasAttribute("src")||(n.textContent=i.textContent),e.parentNode?.replaceChild(n,e)}))}saveScrollPositions(){const e={window:{scrollTop:window.scrollY||document.documentElement.scrollTop,scrollLeft:window.scrollX||document.documentElement.scrollLeft}};return document.querySelectorAll("*").forEach((t=>{(t.scrollTop||t.scrollLeft)&&(e[this.getElementKey(t)]={scrollTop:t.scrollTop,scrollLeft:t.scrollLeft})})),e}getElementKey(e){return e.id||e.className||e.tagName}async redirect(e){if(e)try{const t=new URL(e,window.location.origin);t.origin!==window.location.origin?window.location.href=e:(history.pushState(null,"",e),await this.handleNavigation())}catch(e){console.error("Redirect error:",e)}}abortActiveRequest(){this.activeAbortController&&this.activeAbortController.abort()}async fetch(e,t,n=!1){let s;return n?(this.activeAbortController&&this.activeAbortController.abort(),this.activeAbortController=new AbortController,s=this.activeAbortController):s=new AbortController,fetch(e,{...t,signal:s.signal,headers:{...t?.headers,"X-Requested-With":"XMLHttpRequest"}})}isJsonLike(e){return"string"==typeof e&&((e=e.trim()).startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]"))}parseJson(e){try{return JSON5.parse(e)}catch(e){return console.error(`Error parsing JSON: ${e.message}. Please ensure the JSON string is valid.`,e),null}}parseTime(e){if("number"==typeof e)return e;const t=e.match(/^(\d+)(ms|s|m)?$/);if(t){const e=parseInt(t[1],10);switch(t[2]||"ms"){case"ms":default:return e;case"s":return 1e3*e;case"m":return 60*e*1e3}}return 0}scheduleChange(e,t,n,s){setTimeout((()=>{requestAnimationFrame((()=>{e.style[n]=s}))}),t)}async processInlineModuleScripts(){const e=document.body.querySelectorAll('script[type="module"]:not([src])');for(const t of e){const e=t.textContent?.trim();if(!e||e.startsWith("<"))continue;const n=new Blob([e],{type:"text/javascript"}),s=URL.createObjectURL(n);try{const e=await import(s);for(const[t,n]of Object.entries(e))"function"==typeof n&&(window[t]=n)}catch(e){console.error("Inline module import failed:",e)}finally{URL.revokeObjectURL(s)}}}observeDOMChanges(){new MutationObserver((e=>{for(const t of e)"childList"===t.type&&t.addedNodes.length})).observe(document.body,{childList:!0,subtree:!0})}async fetchFunction(e,t={},n=!1){try{const s={callback:e,...t},i=window.location.href;let r;if(Object.keys(s).some((e=>{const t=s[e];return t instanceof File||t instanceof FileList&&t.length>0}))){const e=new FormData;Object.keys(s).forEach((t=>{const n=s[t];n instanceof File?e.append(t,n):n instanceof FileList?Array.from(n).forEach((n=>e.append(t,n))):e.append(t,n)})),r={method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:e}}else r=this.createFetchOptions(s);const a=await this.fetch(i,r,n);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)}"]`,n=document.querySelector(t);if(n){n.remove();const e=document.createElement("script");Array.from(n.attributes).forEach((t=>{e.setAttribute(t.name,t.value)})),n.src?e.src=n.src:e.textContent=n.textContent,e.type=n.type||"module",document.body.appendChild(e)}}))}async sync(...e){try{const t=this.saveScrollPositions();this.saveState();const n=e.length>0?e.map((e=>`pp-sync="${e}"`)):['pp-sync="true"'],s=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()}),i=await this.fetch(window.location.href,s),r=await i.text(),a=(new DOMParser).parseFromString(r,"text/html"),o=new Set;n.forEach((e=>{const t=document.querySelectorAll(`[${e}]`),n=a.body.querySelectorAll(`[${e}]`);t.forEach(((e,t)=>{const s=n[t];if(s){if(s.hasAttribute("pp-sync-script")){const e=s.getAttribute("pp-sync-script")||"";e&&o.add(e)}s.querySelectorAll("[pp-sync-script]").forEach((e=>{const t=e.getAttribute("pp-sync-script")||"";t&&o.add(t)})),e.innerHTML=s.innerHTML,this.reRunScripts(e)}}))})),this.processSyncScripts(o),this.restoreState(),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),n=await t.text();await this.updateBodyContent(n)}reRunScripts(e){e.querySelectorAll("script").forEach((e=>{const t=document.createElement("script");Array.from(e.attributes).forEach((e=>{t.setAttribute(e.name,e.value)})),e.hasAttribute("src")||(t.textContent=e.textContent),e.parentNode?.replaceChild(t,e)}))}copyCode(e,t,n,s,i="img",r=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(i);if(t)for(const[e,n]of Object.entries(s))e in t?t[e]=n:t.setAttribute(e,n);setTimeout((()=>{if(t)for(const[e,s]of Object.entries(n))e in t?t[e]=s:t.setAttribute(e,s)}),r)}),(()=>{alert("Failed to copy command to clipboard")})):alert("Failed to find the code block to copy")}getCookie(e){return document.cookie.split("; ").find((t=>t.startsWith(e+"=")))?.split("=")[1]||null}}class PPHPLocalStore{static instance=null;state;listeners;pphp;STORAGE_KEY;constructor(e={}){this.state=e,this.listeners=[],this.pphp=PPHP.instance,this.STORAGE_KEY=this.pphp.getCookie("pphp_local_store_key")||"pphp_local_store_59e13",this.loadState()}static getInstance(e={}){return PPHPLocalStore.instance||(PPHPLocalStore.instance=new PPHPLocalStore(e)),PPHPLocalStore.instance}setState(e,t=!1){if(this.state={...this.state,...e},this.listeners.forEach((e=>e(this.state))),this.saveState(),t){const e=localStorage.getItem(this.STORAGE_KEY);e&&this.pphp.fetchFunction(this.STORAGE_KEY,{[this.STORAGE_KEY]:e})}}saveState(){localStorage.setItem(this.STORAGE_KEY,JSON.stringify(this.state))}loadState(){const e=localStorage.getItem(this.STORAGE_KEY);e&&(this.state=this.pphp.parseJson(e),this.listeners.forEach((e=>e(this.state))))}resetState(e,t=!1){if(e?(delete this.state[e],this.saveState()):(this.state={},localStorage.removeItem(this.STORAGE_KEY)),this.listeners.forEach((e=>e(this.state))),t){const t=e?localStorage.getItem(this.STORAGE_KEY):null;this.pphp.fetchFunction(this.STORAGE_KEY,{[this.STORAGE_KEY]:t})}}}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 n=this.params;n.set(e,t),this.updateURL(n)}delete(e){const t=this.params;t.delete(e),this.updateURL(t)}replace(e){const t=new URLSearchParams;for(const n in e){const s=e[n];null!==s&&t.set(n,s)}this.updateURL(t,!0)}updateURL(e,t=!1){const n=`${window.location.pathname}?${e.toString()}`;t?history.replaceState(null,"",n):history.pushState(null,"",n),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)}))}}document.addEventListener("DOMContentLoaded",(()=>{PPHP.instance.initializeAllReferencedProps(),PPHP.instance.initBindings(),PPHP.instance.initLoopBindings(),PPHP.instance.bindings.forEach((e=>e.update())),PPHP.instance.attachWireFunctionEvents(),PPHP.instance.processInlineModuleScripts(),requestAnimationFrame((()=>{document.body.classList.add("pp-hydrated")}))}));var pphp=PPHP.instance,store=PPHPLocalStore.getInstance(),searchParams=SearchParamsManager.getInstance();
|
|
1
|
+
(()=>{const e=EventTarget.prototype.addEventListener,t=EventTarget.prototype.removeEventListener,n=new Map;EventTarget.prototype.addEventListener=function(t,s,i){n.has(this)||n.set(this,new Map);const r=n.get(this).get(t)||new Set;r.add(s),n.get(this).set(t,r),e.call(this,t,s,i)},EventTarget.prototype.removeEventListener=function(e,s,i){if(n.has(this)&&n.get(this).has(e)){const t=n.get(this).get(e);t&&(t.delete(s),0===t.size&&n.get(this).delete(e))}t.call(this,e,s,i)},EventTarget.prototype.removeAllEventListeners=function(e){if(n.has(this)&&n.get(this).has(e)){const s=n.get(this).get(e);s&&(s.forEach((n=>{t.call(this,e,n)})),n.get(this).delete(e))}}})();class PPHP{props={};static _instance;_isNavigating=!1;_responseData=null;_activeAbortController=null;_rawProps={};_elementState={checkedElements:new Set};_reservedWords;_bindings=[];_pendingBindings=new Set;_updateScheduled=!1;_templateStore=new WeakMap;_proxyCache=new WeakMap;_scopedKeys=new Map;_processedPhpSections=new Set;_processedPhpScripts=new WeakSet;_effects=new Set;_pendingEffects=new Set;_builtInProps;_eventHandlers;_redirectRegex=/redirect_7F834\s*=\s*(\/[^\s]*)/;_mustacheRe=/\{\{\s*([\s\S]+?)\s*\}\}/gu;_assignmentRe=/^\s*[\w.]+\s*=(?!=)/;_htmlEntitiesRe=/"|'|&/g;_mutators;_arrayMethodCache=new WeakMap;static _pathPattern=/\b([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\b/g;static _mustacheTest=/\{\{\s*[\s\S]+?\s*\}\}/;static _mustachePattern=/\{\{\s*([\s\S]+?)\s*\}\}/g;constructor(){const e=Object.getOwnPropertyNames(HTMLElement.prototype).filter((e=>e.startsWith("on"))),t=Object.getOwnPropertyNames(Document.prototype).filter((e=>e.startsWith("on"))),n=Object.getOwnPropertyNames(Window.prototype).filter((e=>e.startsWith("on")));this._eventHandlers=new Set([...e,...t,...n].map((e=>e.toLowerCase()))),this._builtInProps=new Set(["length","charAt","charCodeAt","codePointAt","concat","includes","endsWith","indexOf","lastIndexOf","localeCompare","match","matchAll","normalize","padEnd","padStart","repeat","replace","replaceAll","search","slice","split","substring","substr","startsWith","toLocaleLowerCase","toLocaleUpperCase","toLowerCase","toString","toUpperCase","trim","trimEnd","trimStart","valueOf"]),this._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"]),this._mutators=new Set(["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"]),this.handlePopState(),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.processInlineModuleScripts(),this.initializeAllReferencedProps(),this.initBindings(),this.initLoopBindings(),this.attachWireFunctionEvents(),this._bindings.forEach((e=>e.update())),requestAnimationFrame((()=>document.documentElement.setAttribute("data-initial-hydrated","")))};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>e()),{once:!0}):e()}_currentSectionId(){const e=document.currentScript;return e?.closest("[pp-section-id]")?.getAttribute("pp-section-id")||null}getNested(e,t){return t.split(".").reduce(((e,t)=>e?e[t]:void 0),e)}setNested(e,t,n){const s=t.split("."),i=s.pop();s.reduce(((e,t)=>e[t]??={}),e)[i]=n}hasNested(e,t){return void 0!==this.getNested(e,t)}scopeKey(e){const t=this._currentSectionId();return t?e.startsWith(`${t}_`)?e:e.includes(".")?e.replace(/^([^\.]+)/,`${t}_$1`):`${t}_${e}`:e}alreadyScoped(e,t){const n=`${t}_${e}`;return this._scopedKeys.get(t)?.has(n)??!1}effect(e,t){const n=this._currentSectionId(),s=Array.isArray(t),i=s?t:[],r=s&&0===i.length,o=i.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,n]of this._scopedKeys)if(n.has(e))return`${t}_${e}`;return n?`${n}_${e}`:e})).filter(Boolean);if(e.__deps=new Set(o),r){try{e()}catch(e){console.error("effect error:",e)}return()=>{}}const a=(window.__PPHP_INLINE_DEPTH__??0)>0?this._pendingEffects:this._effects;return a.delete(e),a.add(e),()=>{this._effects.delete(e),this._pendingEffects.delete(e)}}state(e,t){const n=this._currentSectionId(),s=e;e=this.scopeKey(e),n&&(this._scopedKeys.has(n)||this._scopedKeys.set(n,new Set),this._scopedKeys.get(n).add(s)),this.hasNested(pphp.props,e)||this.setNested(pphp.props,e,t);const i=()=>this.getNested(pphp.props,e),r=()=>i();return Object.defineProperties(r,{valueOf:{value:()=>i()},toString:{value:()=>String(i())}}),[r,t=>{const n="function"==typeof t?t(i()):t;this.setNested(pphp.props,e,n)}]}extractDependencies(e){const t=e.replace(/\?\./g,".");return new Set(t.match(/\b[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\b/g)||[])}formatValue(e){return"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,n="text",s){if(this._assignmentRe.test(t))return;const i=e.parentElement?.closest("[pp-section-id]"),r=i?.getAttribute("pp-section-id");let o=t;if(r){const e=this._scopedKeys.get(r)??new Set;o=t.replace(/\b([A-Za-z_$][\w$]*)\b/g,((t,n,s,i)=>{const o=e.has(n),a=e.has(r+"_"+n);return o||a?"."===i[s-1]||this._reservedWords.has(n)||t.startsWith(r+"_")?t:r+"_"+n:t}))}const a=new Set([...this.extractDependencies(o)].map((e=>e.split(".")[0])).filter((e=>e in this.props&&!this._reservedWords.has(e)))),c=this.makeSafeEvaluator(o);if("value"===s||"checked"===s){const t=this.makePrimitiveUpdater(e,s,c);return void this._bindings.push({dependencies:a,update:t})}if(s){const t=e.getAttribute(s)??"";if(this._mustacheRe.test(o)||this._mustacheRe.test(t)){const n=this._mustacheRe.test(o)?o:t,i=this.makeAttrTemplateUpdater(e,s,a,n);return void this._bindings.push({dependencies:a,update:i})}const n=()=>{try{const t=c(this.props),n=this.formatValue(t);s in e&&(e[s]=n),e.setAttribute(s,n)}catch(e){console.error(`Error evaluating "${s}"="${o}"`,e)}};return void this._bindings.push({dependencies:a,update:n})}const l={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=c(this.props),s=this.formatValue(t);l[n](e,s)}catch(e){console.error(`Error evaluating expression "${o}".`,e)}}})}makePrimitiveUpdater(e,t,n){const s={};return this._eventHandlers.forEach((e=>{if(e.startsWith("on")){const t=e.slice(2);s[t]=t}})),s.value="input",s.checked="change",()=>{try{const i=n(this.props),r=this.formatValue(i);let o=!1;if("value"===t){const t=e;"value"in e&&t.value!==r?(t.value=r,o=!0):"value"in e||(e.setAttribute("value",r),o=!0)}else{const t=e,n="true"===r;"checked"in e&&t.checked!==n?(t.checked=n,o=!0):"checked"in e||(e.setAttribute("checked",r),o=!0)}if(!o||e instanceof HTMLInputElement&&("hidden"===e.type||e.disabled||e.readOnly))return;const a=e.getAttribute("pp-dispatch-event")||s[t]||t,c="click"===a?new MouseEvent(a,{bubbles:!0,cancelable:!0}):new Event(a,{bubbles:!0});e.dispatchEvent(c)}catch(e){console.error(`Error evaluating attribute "${t}":`,e)}}}makeAttrTemplateUpdater(e,t,n,s){let i=this._templateStore.get(e);i||(i=new Map,this._templateStore.set(e,i)),i.has(t)||i.set(t,e.getAttribute(t)||"");const r=s??i.get(t)??"";return(r.match(this._mustacheRe)||[]).forEach((e=>{this.extractDependencies(e).forEach((e=>n.add(e)))})),()=>{try{const n=r.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)!==n&&e.setAttribute(t,n)}catch(e){console.error(`Error evaluating the template for attribute "${t}". Please check the template syntax and dependencies.`,e)}}}initBindings(){this._bindings=[],document.body.querySelectorAll("*").forEach((e=>{["pp-bind","pp-bind-expr"].forEach((t=>{const n=e.getAttribute(t);n&&this.registerBinding(e,n,"text")})),Array.from(e.attributes).forEach((t=>{if(!t.name.startsWith("pp-bind-"))return;if("pp-bind"===t.name||"pp-bind-expr"===t.name)return;const n=t.value.replace(this._htmlEntitiesRe,(e=>"""===e?'"':"'"===e?"'":"&")).replace(/^{{\s*|\s*}}$/g,"");let s=t.name.replace(/^(pp-bind-)+/,"");const i=s.toLowerCase();"html"!==i&&"innerhtml"!==i||(s="innerHTML");const r="value"===s?"value":"checked"===s?"checked":"text";this.registerBinding(e,n,r,s)}))}))}safeNull=new Proxy({},{get:(e,t)=>t===Symbol.toPrimitive?()=>{}:this._builtInProps.has(t.toString())?()=>"":this.safeNull,apply:()=>""});safeTag=(e,...t)=>e.reduce(((e,n,s)=>{const i=t[s];return e+n+(null==i||"object"==typeof i?"":i)}),"");makeSafeEvaluator(e){let t=e.trim();const n=t.replace(/\?\./g,".");if(/^\(\s*\)\s*=>/.test(t)&&(t=`(${t})()`),t.startsWith("`")&&t.endsWith("`")){const e=new Function("props","safeTag",`\n try {\n with (props) {\n return safeTag${t};\n }\n } catch (e) {\n console.error("PPHP template eval error for:", ${JSON.stringify(t)}, e);\n return "";\n }\n `);return t=>e(t,this.safeTag.bind(this))}const s=n.replace(/(["'])(?:(?=(\\?))\2.)*?\1/g,"").match(/\b[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\b/g)||[],i=new Set(s.map((e=>e.split(".")[0])).filter((e=>/^[A-Za-z_$][\w$]*$/.test(e)&&!this._reservedWords.has(e)&&"safeTag"!==e))),r=Array.from(i).map((e=>`\n const ${e} = ctx["${e}"] !== undefined\n ? ctx["${e}"]\n : (typeof window !== "undefined" && window["${e}"] !== undefined\n ? window["${e}"]\n : ${new RegExp(`\\b${e}\\.`).test(n)?"{}":"void 0"});\n if (typeof window !== "undefined" && window["${e}"] !== ${e}) {\n window["${e}"] = ${e};\n }\n `)).join("\n"),o=/^\s*[\w\.]+\s*=(?!=)/.test(t),a=new Function("ctx","safeTag",`\n "use strict";\n ${r}\n try {\n ${o?t+"; return '';":"const result = "+t+"; return result === undefined || result === null ? '' : result;"}\n } catch (e) {\n return "";\n }\n `);return e=>a(e,this.safeTag.bind(this))}setNestedProperty(e,t,n){const s=t.split(".");let i=e;for(let e=0;e<s.length-1;e++)s[e]in i||(i[s[e]]={}),i=i[s[e]];i[s[s.length-1]]=n}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._processedPhpSections=new Set,this._processedPhpScripts=new WeakSet,this._scopedKeys=new Map,this._effects=new Set,this._pendingEffects=new Set,this._bindings=[],this.props=this.makeReactive(this._rawProps)}initializeAllReferencedProps(){const e=PPHP._pathPattern,t=PPHP._mustachePattern,n=PPHP._mustacheTest,s=this.props,i=this._builtInProps,r=new Set,o=(e,t)=>{const n=e.getAttribute("pp-section-id"),s=e.parentElement?.closest("[pp-section-id]")?.getAttribute("pp-section-id")??null,i=e.hasAttribute(`data-override-${t}`)?s:n??s;return i?`${i}_${t}`:t};for(const s of document.body.getElementsByTagName("*"))for(const{name:a,value:c}of Array.from(s.attributes)){if(c&&n.test(c))for(const n of c.matchAll(t))for(const t of n[1].matchAll(e)){const[e,...n]=t[1].split(".");if(i.has(e))continue;const a=o(s,e);r.add(n.length?`${a}.${n.join(".")}`:a)}if(a.startsWith("pp-bind")){const t=a.slice(8);for(const n of c.matchAll(e)){const e=n[1],[o,...a]=e.split(".");if(i.has(o))continue;const c=s.hasAttribute(`data-override-${t}`),l=s.getAttribute("pp-section-id"),h=s.parentElement?.closest("[pp-section-id]")?.getAttribute("pp-section-id")??null,p=c?h:l??h,d=p?`${p}_${o}`:o,u=a.length?`${d}.${a.join(".")}`:d;r.add(u)}}}const a=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT,{acceptNode:e=>n.test(e.nodeValue||"")?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT});let c;for(;c=a.nextNode();){const n=c.nodeValue,s=c.parentElement;for(const a of n.matchAll(t))for(const t of a[1].matchAll(e)){const[e,...n]=t[1].split(".");if(i.has(e))continue;const a=o(s,e);r.add(n.length?`${a}.${n.join(".")}`:a)}}for(const e of r){const t=e.split(".");let n=s;for(let e=0;e<t.length;e++){const s=t[e];if(i.has(s)||null==n||"object"!=typeof n)break;s in n||(n[s]=e===t.length-1?void 0:{}),n=n[s]}}const l=new Set;for(const e of r)l.add(e.split(".")[0]);for(const e of l)e in globalThis||Object.defineProperty(globalThis,e,{configurable:!0,enumerable:!0,get:()=>s[e],set:t=>{s[e]=t}})}scheduleBindingUpdate(e){this._pendingBindings.add(e),this._updateScheduled||(this._updateScheduled=!0,requestAnimationFrame((()=>{this.flushBindings()})))}flushBindings(){const e=new Set;this._pendingBindings.forEach((t=>{t.dependencies.forEach((t=>e.add(t))),t.update()})),this._pendingBindings.clear(),this._updateScheduled=!1,this._effects.forEach((t=>{const n=t.__deps||new Set;if(0===n.size||[...n].some((t=>e.has(t))))try{t()}catch(e){console.error("effect error:",e)}}))}initMakeReactive(){this.initializeAllReferencedProps(),this.initBindings(),this.initLoopBindings(),this.attachWireFunctionEvents(),this._bindings.forEach((e=>e.update()))}getProxiedProps(e){let t=this._proxyCache.get(e);if(t)return t;return t=new Proxy(e,{get:(e,t)=>t in e?e[t]:void 0,set:(e,t,n)=>(e[t]=n,!0)}),this._proxyCache.set(e,t),t}async invokeHandler(e,t,n){try{const s=t.trim(),i=s.replace(/(["'`])(?:\\.|(?!\1).)*\1/g,"").replace(/\/(?:\\.|[^\/])+\/[gimsuy]*/g,"");if(/^\(?\s*[^=]*?\)?\s*=>/.test(i.trim())){const t=new Function("event","proxy","props",`\n with (proxy) {\n const val = (${s});\n return (typeof val === "function")\n ? val.call(this, event, props)\n : val;\n }\n `),i=this.getProxiedProps(pphp.props);return void await t.call(e,n,i,pphp.props)}const r=t.match(/^(\w+(\.\w+)*)\((.*)\)$/);if(r){const s=r[1],i=r[3],o=s.split("."),{context:a,methodName:c}=this.resolveContext(o);if("function"==typeof a[c])if(this.isJsonLike(i)){const t=this.parseJson(i);t.element=e,t.event=n;const s=[t];await a[c](...s)}else new Function("event",t).call(e,n);else await this.handleParsedCallback(e,t)}else if(t.includes("=")){const s=t.match(/^\s*([\w\.]+)\s*=/);if(s){const e=s[1];if(e.includes(".")){const t=e.split(".");let n=pphp.props;for(let e=0;e<t.length-1;e++){const s=t[e];s in n&&null!=n[s]&&"object"==typeof n[s]||(n[s]={}),n=n[s]}}else e in pphp.props||(pphp.props[e]=void 0)}new Function("event","props",`\n with (new Proxy(props, {\n get(target, key) {\n return key in target ? target[key] : undefined;\n },\n set(target, key, value) {\n target[key] = value;\n return true;\n }\n })) {\n ${t}\n }\n `).call(e,n,pphp.props)}else await this.handleParsedCallback(e,t)}catch(e){console.error(`Error executing handler "${t}". Please ensure the handler is defined and valid.`,e)}}registerLoop(e){const t=e.getAttribute("pp-for").trim(),[n,s]=t.split(/\s+in\s+/),[i,r]=n.replace(/^\(|\)$/g,"").split(",").map((e=>e.trim())),o=e.parentNode,a=document.createComment("pp-for");o.insertBefore(a,e),o.removeChild(e);const c=this.makeSafeEvaluator(s),l=this.extractDependencies(s);this._bindings.push({dependencies:l,update:()=>{let t=a.nextSibling;for(;t&&t.nodeType!==Node.COMMENT_NODE;){const e=t.nextSibling;o.removeChild(t),t=e}(c(this.props)||[]).forEach(((t,n)=>{this.props[i]=t,r&&(this.props[r]=n);const s=e.content.cloneNode(!0);s.querySelectorAll("[pp-bind]").forEach((e=>{const t=e.getAttribute("pp-bind"),n=this.makeSafeEvaluator(t)(this.props);e.textContent=this.formatValue(n)})),s.querySelectorAll("*").forEach((e=>{Array.from(e.attributes).forEach((t=>{if(t.name.startsWith("on")&&/\bi\b/.test(t.value)){const s=t.value.replace(/\bi\b/g,String(n));e.setAttribute(t.name,s)}}))})),o.insertBefore(s,a.nextSibling)})),this.attachWireFunctionEvents()}})}initLoopBindings(){document.querySelectorAll("[pp-for]").forEach((e=>this.registerLoop(e)))}makeReactive(e,t=[]){const n=this._proxyCache.get(e);if(n)return n;const s=this;if(e instanceof Map||e instanceof Set)return e;const i=new Proxy(e,{get(e,n,i){const r=Reflect.get(e,n,i);if(Array.isArray(e)&&s._mutators.has(n)){let o=s._arrayMethodCache.get(e);if(o||(o=new Map,s._arrayMethodCache.set(e,o)),!o.has(n)){const e=r,a=t.join("."),c=function(...t){const n=Reflect.apply(e,i,t);return queueMicrotask((()=>{s._bindings.forEach((e=>{e.dependencies.has(a)&&s.scheduleBindingUpdate(e)}))})),n};o.set(n,c)}return o.get(n)}return"object"==typeof r&&null!==r?s.makeReactive(r,[...t,n]):r},set(e,n,i){i&&"object"==typeof i&&(i=s.makeReactive(i,[...t,n.toString()])),e[n]=i;const r=[...t,n].join(".");return s._bindings.forEach((e=>{for(const t of e.dependencies)if(r===t||r.startsWith(t+".")||t.startsWith(r+".")){s.scheduleBindingUpdate(e);break}})),!0}});return this._proxyCache.set(e,i),i}handlePopState(){window.addEventListener("popstate",(async()=>{await this.handleNavigation()}))}prefixFunctionCalls(e,t){return e.replace(/\b([A-Za-z_$][\w$]*)\s*\(/g,((e,n)=>this._reservedWords.has(n)||n.startsWith(`${t}_`)?e:this.alreadyScoped(n,t)?`${t}_${n}(`:e))}prefixIds(e,t){let n="",s=0,i=(e=this.prefixFunctionCalls(e,t)).length,r=!1,o=!1,a=!1;for(;s<i;){const c=e[s];if("'"!==c||o||a||"\\"===e[s-1])if('"'!==c||r||a||"\\"===e[s-1])if("`"!==c||r||o||"\\"===e[s-1])if(r||o||a)n+=c,s++;else if(/[A-Za-z_$]/.test(c)){let r=s+1;for(;r<i&&/[\w$]/.test(e[r]);)r++;const o=e.slice(s,r),a=e[s-1]??"",c=this._reservedWords.has(o),l="."===a;n+=!o.startsWith(`${t}_`)&&!l&&!c?`${t}_${o}`:o,s=r}else n+=c,s++;else a=!a,n+=c,s++;else o=!o,n+=c,s++;else r=!r,n+=c,s++}return n}attachWireFunctionEvents(){this.handleHiddenAttribute(),this.handleAnchorTag();const e=Array.from(this._eventHandlers).map((e=>`[${e}]`)).join(", ");document.body.querySelectorAll(e).forEach((e=>{const t=e.closest("[pp-section-id]")?.getAttribute("pp-section-id");if(Array.from(e.attributes).filter((e=>this._eventHandlers.has(e.name))).forEach((n=>{const s=n.name.slice(2);e.removeAllEventListeners(s);let i=n.value.trim();if(t){const e=i.indexOf("=>");if(-1!==e){const n=i.slice(0,e+2),s=i.slice(e+2);i=n+this.prefixIds(s,t)}else i=this.prefixIds(i,t)}e instanceof HTMLInputElement&&this.handleInputAppendParams(e,s),e.removeAttribute(n.name),this.handleDebounce(e,s,i)})),e instanceof HTMLFormElement){const n=e.getAttribute("onsubmit")?.trim();if(n){let s=n;t&&(s=s.replace(/^([A-Za-z_$][\w$]*)\s*\(/,((e,n)=>`${t}_${n}(`))),e.removeAttribute("onsubmit"),this.handleDebounce(e,"submit",s)}}}))}async handleDebounce(e,t,n){const s=e.getAttribute("pp-debounce")||"",i=e.getAttribute("pp-before-request")||"",r=e.getAttribute("pp-after-request")||"",o=async t=>{t.preventDefault();try{i&&await this.invokeHandler(e,i,t),await this.invokeHandler(e,n,t),r&&"@close"!==r&&await this.invokeHandler(e,r,t),this.handlerAutofocusAttribute()}catch(e){console.error("Error in debounced handler. Please check the handler logic and ensure it is functioning correctly.",e)}};if(s){const n=this.parseTime(s),i=this.debounce(o,n);e instanceof HTMLFormElement&&"submit"===t?e.addEventListener(t,(e=>{e.preventDefault(),i(e)})):e.addEventListener(t,i)}else e.addEventListener(t,o)}debounce(e,t=300,n=!1){let s;return function(...i){const r=this;s&&clearTimeout(s),s=setTimeout((()=>{s=null,n||e.apply(r,i)}),t),n&&!s&&e.apply(r,i)}}handlerAutofocusAttribute(){const e=document.activeElement;if(e&&e!==document.body)return;const t=this._elementState?.focusId;if(!t)return;const n=document.querySelectorAll("[pp-autofocus]");let s=!1;n.forEach((e=>{if(s)return;const t=e.getAttribute("pp-autofocus");if(!t||!this.isJsonLike(t))return;const n=this.parseJson(t);if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e instanceof HTMLInputElement)if(["text","search","tel","url","password"].includes(e.type))if("number"===e.type){e.type="text";const t=e.value.length||0;e.setSelectionRange(t,t),e.type="number"}else this.setCursorPosition(e,n);else;else e instanceof HTMLTextAreaElement&&this.setCursorPosition(e,n)}e.focus(),s=!0}))}async handleParsedCallback(e,t){const{funcName:n,data:s}=this.parseCallback(e,t);if(!n)return;const i=this[n],r=window[n];let o;if("function"==typeof i?o=i:"function"==typeof r&&(o=r),"function"==typeof o){const t=e.hasAttribute("pp-after-request"),n=Array.isArray(s.args)?s.args:[],i=this._responseData?this.parseJson(this._responseData):{response:this._responseData};let r={args:n,element:e,data:s};t&&(r={...r,...i}),await o.call(this,r)}else this._responseData=null,this._responseData=await this.handleUndefinedFunction(e,n,s)}async handleUndefinedFunction(e,t,n){const s={callback:t,...n},i=this.createFetchOptions(s),r=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});try{this.saveElementOriginalState(e),this.handleSuspenseElement(e);const s=new URL(window.location.href);let o="",a="",c={success:!1};const l=e.querySelector("input[type='file']");if(l){if(o=await this.fetchFileWithData(s.href,t,l,n),a=this.extractJson(o)||"",a)try{c=this.parseJson(a)}catch(e){console.error("Error parsing JSON response. Please ensure the response is in valid JSON format.",e)}}else{const e=await this.fetch(s.href,i);if(o=await e.text(),this.getRedirectUrl(o))return void await this.redirect(this.getRedirectUrl(o)||"");if(a=this.extractJson(o)||"",a)try{c=this.parseJson(a)}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=o.replace(a,"")}else e=o;if(this.appendAfterbegin(e),!p&&!c.success)return}if(p&&c.success){this.handleAfterRequest(p,a);const e=o.replace(a,"");return this.appendAfterbegin(e),a}if("@close"===p)return c.success?a:void 0;const d=await this.fetch(s.href,r),u=await d.text();if(this.getRedirectUrl(u))return void await this.redirect(this.getRedirectUrl(u)||"");await this.handleResponseRedirectOrUpdate(o,u,a,c)}catch(e){console.error(`Error handling undefined function "${t}". Please ensure the function is defined and accessible.`,e)}}handleAfterRequest(e,t){if(!this.isJsonLike(e))return;const n=this.parseJson(e),s=t?this.parseJson(t):null,i=n.targets;Array.isArray(i)&&i.forEach((e=>{const{id:t,...n}=e,i=document.querySelector(t);let r={};if(s){for(const t in n)if(n.hasOwnProperty(t))switch(t){case"innerHTML":case"outerHTML":case"textContent":case"innerText":"response"===n[t]&&(r[t]=e.responseKey?s[e.responseKey]:s.response);break;default:r[t]=n[t]}}else r=n;i&&this.updateElementAttributes(i,r)}))}async handleResponseRedirectOrUpdate(e,t,n,s){const i=this.getUpdatedHTMLContent(e,n,s),r=(new DOMParser).parseFromString(t,"text/html");i&&r.body.insertAdjacentElement("afterbegin",i),this.updateBodyContent(r.body.outerHTML)}getUpdatedHTMLContent(e,t,n){const s=document.createElement("div");if(s.id="afterbegin-8D95D",n&&t?.success){const t=e.replace(n,"");s.innerHTML=t}else s.innerHTML=e;return s.innerHTML?s:null}async updateBodyContent(e){const t=this.saveScrollPositions();this.saveElementState();const n=(new DOMParser).parseFromString(e,"text/html");await this.appendCallbackResponse(n),this.restoreElementState(),this.restoreScrollPositions(t),await this.processInlineModuleScripts(),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 n in t)if(t.hasOwnProperty(n))switch(n){case"innerHTML":case"outerHTML":case"textContent":case"innerText":e[n]=this.decodeHTML(t[n]);break;case"insertAdjacentHTML":e.insertAdjacentHTML(t.position||"beforeend",this.decodeHTML(t[n].html));break;case"insertAdjacentText":e.insertAdjacentText(t.position||"beforeend",this.decodeHTML(t[n].text));break;case"setAttribute":e.setAttribute(t.attrName,this.decodeHTML(t[n]));break;case"removeAttribute":e.removeAttribute(t[n]);break;case"className":e.className=this.decodeHTML(t[n]);break;case"classList.add":e.classList.add(...this.decodeHTML(t[n]).split(","));break;case"classList.remove":e.classList.remove(...this.decodeHTML(t[n]).split(","));break;case"classList.toggle":e.classList.toggle(this.decodeHTML(t[n]));break;case"classList.replace":const[s,i]=this.decodeHTML(t[n]).split(",");e.classList.replace(s,i);break;case"dataset":e.dataset[t.attrName]=this.decodeHTML(t[n]);break;case"style":Object.assign(e.style,t[n]);break;case"value":e.value=this.decodeHTML(t[n]);break;case"checked":e.checked=t[n];break;default:e.setAttribute(n,this.decodeHTML(t[n]))}}decodeHTML(e){const t=document.createElement("textarea");return t.innerHTML=e,t.value}appendAfterbegin(e){if(!e)return;const t="afterbegin-8D95D";let n=document.getElementById(t);n?(n.innerHTML=e,document.body.insertAdjacentElement("afterbegin",n)):(n=document.createElement("div"),n.id=t,n.innerHTML=e,document.body.insertAdjacentElement("afterbegin",n))}restoreSuspenseElement(e){const t=e.getAttribute("pp-original-state");if(e.hasAttribute("pp-suspense")&&t){const n=(e,t)=>{for(const n in t)t.hasOwnProperty(n)&&("textContent"===n?e.textContent=t[n]:"innerHTML"===n?e.innerHTML=t[n]:"disabled"===n?!0===t[n]?e.setAttribute("disabled","true"):e.removeAttribute("disabled"):e.setAttribute(n,t[n]));for(const n of Array.from(e.attributes))t.hasOwnProperty(n.name)||e.removeAttribute(n.name)},s=(e,t)=>{for(const s in t)if(t.hasOwnProperty(s))for(const t of Array.from(e.elements))if(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement){const e=t.getAttribute("pp-original-state")||"";if(e){if(this.isJsonLike(e)){const s=this.parseJson(e);n(t,s)}else i(t,e);t.removeAttribute("pp-original-state")}}},i=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},r=(e,t)=>{e instanceof HTMLFormElement?s(e,t):n(e,t)};try{const i=this.parseJson(t);if(i)if(e instanceof HTMLFormElement){const t=e.id;if(t){const e=document.querySelector(`[form="${t}"]`);if(e){const t=e.getAttribute("pp-original-state");if(t&&this.isJsonLike(t)){const s=this.parseJson(t);n(e,s)}}}const i=new FormData(e),r={};if(i.forEach(((e,t)=>{r[t]=e})),s(e,r),e.hasAttribute("pp-suspense")){const t=e.getAttribute("pp-suspense")||"";if(this.parseJson(t).disabled)for(const t of Array.from(e.elements))(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&t.removeAttribute("disabled")}}else if(i.targets){i.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&r(s,n)}));const{targets:t,...s}=i;n(e,s)}else{const{empty:t,...s}=i;n(e,s)}}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,n,s={}){const i=new FormData,r=n.files;if(r)for(let e=0;e<r.length;e++)i.append("file[]",r[e]);i.append("callback",t);for(const e in s)s.hasOwnProperty(e)&&i.append(e,s[e]);const o=await this.fetch(e,{method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:i});return await o.text()}async handleSuspenseElement(e){let t=e.getAttribute("pp-suspense")||"";const n=(e,t)=>{for(const n in t)if(t.hasOwnProperty(n))for(const t of e.elements)if(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement){const e=t.getAttribute("pp-suspense")||"";if(e)if(this.isJsonLike(e)){const n=this.parseJson(e);"disabled"!==n.onsubmit&&this.updateElementAttributes(t,n),n.targets&&n.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&i(s,n)}))}else s(t,e)}},s=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},i=(e,t)=>{e instanceof HTMLFormElement?n(e,t):this.updateElementAttributes(e,t)};try{if(t&&this.isJsonLike(t)){const s=this.parseJson(t);if(s)if(e instanceof HTMLFormElement){const t=new FormData(e),i={};t.forEach(((e,t)=>{i[t]=e})),s.disabled&&this.toggleFormElements(e,!0);const{disabled:r,...o}=s;this.updateElementAttributes(e,o),n(e,i)}else if(s.targets){s.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&i(s,n)}));const{targets:t,...n}=s;this.updateElementAttributes(e,n)}else{if("disabled"===s.empty&&""===e.value)return;const{empty:t,...n}=s;this.updateElementAttributes(e,n)}}else if(t)s(e,t);else if(e instanceof HTMLFormElement){const t=new FormData(e),s={};t.forEach(((e,t)=>{s[t]=e})),n(e,s)}}catch(e){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 n=0;n<e.attributes.length;n++){const s=e.attributes[n];t[s.name]=s.value}e.setAttribute("pp-original-state",JSON.stringify(t))}if(e instanceof HTMLFormElement){let t=null;const n=e.id;n&&(t=document.querySelector(`[form="${n}"]`)),n&&t||(t=Array.from(e.elements).find((e=>e instanceof HTMLButtonElement||e instanceof HTMLInputElement))),t?t.hasAttribute("pp-original-state")||this.saveElementOriginalState(t):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,n)=>{e[n]=t})),e}createFetchOptions(e){return{method:"POST",headers:{"Content-Type":"application/json",HTTP_PPHP_WIRE_REQUEST:"true"},body:JSON.stringify(e)}}parseCallback(e,t){let n={};const s=e.closest("form");if(s){new FormData(s).forEach(((e,t)=>{n[t]?Array.isArray(n[t])?n[t].push(e):n[t]=[n[t],e]:n[t]=e}))}else e instanceof HTMLInputElement?n=this.handleInputElement(e):(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(n[e.name]=e.value);const i=t.match(/(\w+)\((.*)\)/);if(i){const e=i[1];let t=i[2].trim();if(t.startsWith("{")&&t.endsWith("}"))try{const e=this.parseJson(t);"object"==typeof e&&null!==e&&(n={...n,...e})}catch(e){console.error(`Error parsing JSON: ${e instanceof Error?e.message:"Unknown error"}. Please ensure the JSON string is valid.`,e)}else{const e=t.split(/,(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/).map((e=>e.trim().replace(/^['"]|['"]$/g,"")));n.args=e}return{funcName:e,data:n}}return{funcName:t,data:n}}handleInputElement(e){let t={};if(e.name)if("checkbox"===e.type)t[e.name]={value:e.value,checked:e.checked};else if("radio"===e.type){const n=document.querySelector(`input[name="${e.name}"]:checked`);t[e.name]=n?n.value:null}else t[e.name]=e.value;else"checkbox"===e.type||"radio"===e.type?t.value=e.checked:t.value=e.value;return t}resolveContext(e){let t=window;for(let n=0;n<e.length-1;n++)if(t=t[e[n]],!t)throw new Error(`Cannot find object ${e[n]} in the context.`);return{context:t,methodName:e[e.length-1]}}setCursorPosition(e,t){if(t.start)e.setSelectionRange(0,0);else if(t.end){const t=e.value.length||0;e.setSelectionRange(t,t)}else if(t.length){const n=parseInt(t.length,10)||0;e.setSelectionRange(n,n)}}handleInputAppendParams(e,t){const n=e.getAttribute("pp-append-params"),s=e.getAttribute("pp-append-params-sync");if("true"===n){if("true"===s){const t=e.name||e.id;if(t){const n=new URL(window.location.href),s=new URLSearchParams(n.search);s.has(t)&&(e.value=s.get(t)||"")}}e.addEventListener(t,(e=>{const t=e.currentTarget,n=t.value,s=new URL(window.location.href),i=new URLSearchParams(s.search),r=t.name||t.id;if(r){n?i.set(r,n):i.delete(r);const e=i.toString()?`${s.pathname}?${i.toString()}`:s.pathname;history.replaceState(null,"",e)}}))}}handleHiddenAttribute(){const e=document.querySelectorAll("[pp-visibility]"),t=document.querySelectorAll("[pp-display]"),n=this.handleElementVisibility.bind(this),s=this.handleElementDisplay.bind(this);e.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-visibility",n))),t.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-display",s)))}handleVisibilityElementAttribute(e,t,n){const s=e.getAttribute(t);if(s)if(this.isJsonLike(s)){n(e,this.parseJson(s))}else{const n=this.parseTime(s);if(n>0){const s="pp-visibility"===t?"visibility":"display",i="visibility"===s?"hidden":"none";this.scheduleChange(e,n,s,i)}}}handleElementVisibility(e,t){this.handleElementChange(e,t,"visibility","hidden","visible")}handleElementDisplay(e,t){this.handleElementChange(e,t,"display","none","block")}handleElementChange(e,t,n,s,i){const r=t.start?this.parseTime(t.start):0,o=t.end?this.parseTime(t.end):0;r>0?(e.style[n]=s,this.scheduleChange(e,r,n,i),o>0&&this.scheduleChange(e,r+o,n,s)):o>0&&this.scheduleChange(e,o,n,s)}handleAnchorTag(){document.querySelectorAll("a").forEach((e=>{e.addEventListener("click",(async e=>{const t=e.currentTarget,n=t.getAttribute("href"),s=t.getAttribute("target");if(n&&"_blank"!==s&&!e.metaKey&&!e.ctrlKey&&(e.preventDefault(),!this._isNavigating)){this._isNavigating=!0;try{if(/^(https?:)?\/\//i.test(n)&&!n.startsWith(window.location.origin))window.location.href=n;else{const e=t.getAttribute("pp-append-params");if(n.startsWith("?")&&"true"===e){const e=new URL(window.location.href),t=new URLSearchParams(e.search);let s="";const[i,r]=n.split("#");r&&(s=`#${r}`);new URLSearchParams(i.split("?")[1]).forEach(((e,n)=>{t.set(n,e)}));const o=`${e.pathname}?${t.toString()}${s}`;history.pushState(null,"",o)}else{const[e,t]=n.split("#"),s=`${e}${t?`#${t}`:""}`;history.pushState(null,"",s)}const s=n.indexOf("#");if(-1!==s){const e=n.slice(s+1),t=document.getElementById(e);if(t)t.scrollIntoView({behavior:"smooth"});else{await this.handleNavigation();const t=document.getElementById(e);t&&t.scrollIntoView({behavior:"smooth"})}}else await this.handleNavigation()}}catch(e){console.error("Anchor click error:",e)}finally{this._isNavigating=!1}}}))}))}async handleNavigation(){try{const e=document.getElementById("loading-file-1B87E");if(e){const t=this.findLoadingElement(e,window.location.pathname);t&&await this.updateContentWithTransition(t)}const t=await this.fetch(window.location.href);if(!t.ok)return void console.error(`Navigation error: ${t.status} ${t.statusText}`);const n=await t.text(),s=n.match(this._redirectRegex);if(s&&s[1])return void await this.redirect(s[1]);await this.updateDocumentContent(n)}catch(e){console.error("Navigation error:",e)}}findLoadingElement(e,t){let n=t;for(;;){const t=e.querySelector(`div[pp-loading-url='${n}']`);if(t)return t;if("/"===n)break;const s=n.lastIndexOf("/");n=s<=0?"/":n.substring(0,s)}return e.querySelector("div[pp-loading-url='/' ]")}async updateContentWithTransition(e){const t=document.querySelector("[pp-loading-content='true']")||document.body;if(!t)return;const{fadeIn:n,fadeOut:s}=this.parseTransition(e);await this.fadeOut(t,s),t.innerHTML=e.innerHTML,this.fadeIn(t,n)}parseTransition(e){let t=250,n=250;const s=e.querySelector("[pp-loading-transition]"),i=s?.getAttribute("pp-loading-transition");if(i)try{const e=this.parseJson(i);t=this.parseTime(e.fadeIn??t),n=this.parseTime(e.fadeOut??n)}catch(e){console.error("Failed to parse pp-loading-transition attribute:",e)}return{fadeIn:t,fadeOut:n}}fadeOut(e,t){return new Promise((n=>{e.style.transition=`opacity ${t}ms ease-out`,e.style.opacity="0",setTimeout((()=>{e.style.transition="",n()}),t)}))}fadeIn(e,t){e.style.transition=`opacity ${t}ms ease-in`,e.style.opacity="1",setTimeout((()=>{e.style.transition=""}),t)}async updateDocumentContent(e){const t=this.saveScrollPositions(),n=(new DOMParser).parseFromString(e,"text/html"),s="pp-dynamic-script",i="pp-dynamic-link";document.head.querySelectorAll("[pp-dynamic-meta]").forEach((e=>e.remove()));document.head.querySelectorAll(`[${i}]`).forEach((e=>e.remove()));document.head.querySelectorAll(`[${s}]`).forEach((e=>e.remove()));await(async e=>{Array.from(e.head.children).forEach((e=>{const t=e.tagName;if("SCRIPT"===t&&e.hasAttribute(s)){const t=document.createElement("script");Array.from(e.attributes).forEach((e=>t.setAttribute(e.name,e.value))),e.textContent&&(t.textContent=e.textContent),document.head.appendChild(t)}else if("META"===t){if(e.getAttribute("charset")||"viewport"===e.getAttribute("name"))return;const t=e.name,n=e.getAttribute("property"),s=document.head.querySelector(t?`meta[name="${t}"]`:`meta[property="${n}"]`),i=document.head.querySelector("title");s?document.head.replaceChild(e.cloneNode(!0),s):i?.nextSibling?document.head.insertBefore(e.cloneNode(!0),i.nextSibling):document.head.appendChild(e.cloneNode(!0))}else if("TITLE"===t){const t=document.head.querySelector("title");t?document.head.replaceChild(e.cloneNode(!0),t):document.head.appendChild(e.cloneNode(!0))}else if("LINK"===t){const t=t=>{const n=document.head.querySelector('link[rel="icon"]');if(n)document.head.replaceChild(e.cloneNode(!0),n);else{const e=document.createElement("link");e.rel="icon",e.href=t,document.head.appendChild(e)}};if("icon"===e.getAttribute("rel")){t(e.href)}else if(e.hasAttribute(i)){const t=e.cloneNode(!0);document.head.appendChild(t)}}})),await this.populateDocumentBody(e)})(n),this.restoreScrollPositions(t),this.resetProps(),await this.processInlineModuleScripts(),this.initMakeReactive()}restoreScrollPositions(e){requestAnimationFrame((()=>{const t=e.window;t&&window.scrollTo(t.scrollLeft,t.scrollTop),document.querySelectorAll("*").forEach((t=>{const n=this.getElementKey(t);e[n]&&(t.scrollTop=e[n].scrollTop,t.scrollLeft=e[n].scrollLeft)}))}))}async populateDocumentBody(e){try{morphdom(document.body,e.body,{getNodeKey:e=>1===e.nodeType&&e.hasAttribute("key")?e.getAttribute("key"):void 0,onBeforeElUpdated:(e,t)=>{if("INPUT"===e.nodeName&&e.type.match(/^(text|search)$/)&&e.isSameNode(document.activeElement)){const n=e,s=t;return s.value=n.value,s.selectionStart=n.selectionStart,s.selectionEnd=n.selectionEnd,!1}return"SCRIPT"!==e.tagName||"SCRIPT"!==t.tagName},onBeforeNodeDiscarded:e=>{if(e instanceof HTMLElement){const{timerId:t}=e.dataset;t&&clearTimeout(Number(t))}return!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,n=!1){let s;return n?(this._activeAbortController&&this._activeAbortController.abort(),this._activeAbortController=new AbortController,s=this._activeAbortController):s=new AbortController,fetch(e,{...t,signal:s.signal,headers:{...t?.headers,"X-Requested-With":"XMLHttpRequest"}})}isJsonLike(e){return"string"==typeof e&&((e=e.trim()).startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]"))}parseJson(e){try{return JSON5.parse(e)}catch(e){return console.error(`Error parsing JSON: ${e.message}. Please ensure the JSON string is valid.`,e),null}}parseTime(e){if("number"==typeof e)return e;const t=e.match(/^(\d+)(ms|s|m)?$/);if(t){const e=parseInt(t[1],10);switch(t[2]||"ms"){case"ms":default:return e;case"s":return 1e3*e;case"m":return 60*e*1e3}}return 0}scheduleChange(e,t,n,s){setTimeout((()=>{requestAnimationFrame((()=>{e.style[n]=s}))}),t)}async processInlineModuleScripts(){const e=window;e.__PPHP_INLINE_DEPTH__=(e.__PPHP_INLINE_DEPTH__??0)+1;try{const e=Array.from(document.body.querySelectorAll('script[type="text/php"]:not([src])')).filter((e=>{const t=e.getAttribute("pp-section-id")??e.closest("[pp-section-id]")?.getAttribute("pp-section-id")??null;return t?!this._processedPhpSections.has(t):!this._processedPhpScripts.has(e)}));if(0===e.length)return;const t={};for(const n of e){const e=n.getAttribute("pp-section-id")??n.closest("[pp-section-id]")?.getAttribute("pp-section-id")??null;if(!e)continue;const s=n.textContent||"";for(const[,n]of s.matchAll(/export\s+const\s+([A-Za-z_$]\w*)/g))t[n]=e}for(const n of e){const e=n.getAttribute("pp-section-id")??n.closest("[pp-section-id]")?.getAttribute("pp-section-id")??null;let s=(n.textContent||"").trim();e&&(s=s.replace(/(\bpphp\.state\(\s*['"])([^'"]+)(['"])/g,((t,n,s,i)=>n+(s.startsWith(`${e}_`)?s:`${e}_${s}`)+i))),s=s.replace(/\b([A-Za-z_$]\w*)\s*\(/g,((e,n)=>{const s=t[n];return s?`${s}_${n}(`:e}));const i=new Blob([s],{type:"application/javascript"}),r=URL.createObjectURL(i),o=PPHP.prototype._currentSectionId;e&&(PPHP.prototype._currentSectionId=()=>e);try{const t=await import(r);for(const[n,s]of Object.entries(t))if("function"==typeof s){const t=e?`${e}_${n}`:n;window[t]=s}}catch(e){console.error("Inline module import failed:",e)}finally{PPHP.prototype._currentSectionId=o,URL.revokeObjectURL(r),e?this._processedPhpSections.add(e):this._processedPhpScripts.add(n)}}}finally{e.__PPHP_INLINE_DEPTH__--,0===e.__PPHP_INLINE_DEPTH__&&(this._pendingEffects.forEach((e=>{try{e()}catch(e){console.error("effect error:",e)}this._effects.add(e)})),this._pendingEffects.clear())}}async fetchFunction(e,t={},n=!1){try{const s={callback:e,...t},i=window.location.href;let r;if(Object.keys(s).some((e=>{const t=s[e];return t instanceof File||t instanceof FileList&&t.length>0}))){const e=new FormData;Object.keys(s).forEach((t=>{const n=s[t];n instanceof File?e.append(t,n):n instanceof FileList?Array.from(n).forEach((n=>e.append(t,n))):e.append(t,n)})),r={method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:e}}else r=this.createFetchOptions(s);const o=await this.fetch(i,r,n);if(!o.ok)throw new Error(`Fetch failed with status: ${o.status} ${o.statusText}`);const a=await o.text();try{return JSON.parse(a)}catch{return a}}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)}"]`,n=document.querySelector(t);if(n){n.remove();const e=document.createElement("script");Array.from(n.attributes).forEach((t=>{e.setAttribute(t.name,t.value)})),n.src?e.src=n.src:e.textContent=n.textContent,e.type=n.type||"module",document.body.appendChild(e)}}))}async sync(...e){try{const t=this.saveScrollPositions();this.saveElementState();const n=e.length>0?e.map((e=>`pp-sync="${e}"`)):['pp-sync="true"'],s=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()}),i=await this.fetch(window.location.href,s),r=await i.text(),o=(new DOMParser).parseFromString(r,"text/html"),a=new Set;n.forEach((e=>{const t=document.querySelectorAll(`[${e}]`),n=o.body.querySelectorAll(`[${e}]`);t.forEach(((e,t)=>{const s=n[t];if(s){if(s.hasAttribute("pp-sync-script")){const e=s.getAttribute("pp-sync-script")||"";e&&a.add(e)}s.querySelectorAll("[pp-sync-script]").forEach((e=>{const t=e.getAttribute("pp-sync-script")||"";t&&a.add(t)})),e.innerHTML=s.innerHTML,this.reRunScripts(e)}}))})),this.processSyncScripts(a),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),n=await t.text();await this.updateBodyContent(n)}reRunScripts(e){e.querySelectorAll("script").forEach((e=>{const t=document.createElement("script");Array.from(e.attributes).forEach((e=>{t.setAttribute(e.name,e.value)})),e.hasAttribute("src")||(t.textContent=e.textContent),e.parentNode?.replaceChild(t,e)}))}copyCode(e,t,n,s,i="img",r=2e3){if(!(e instanceof HTMLElement))return;const o=e.closest(`.${t}`)?.querySelector("pre code"),a=o?.textContent?.trim()||"";a?navigator.clipboard.writeText(a).then((()=>{const t=e.querySelector(i);if(t)for(const[e,n]of Object.entries(s))e in t?t[e]=n:t.setAttribute(e,n);setTimeout((()=>{if(t)for(const[e,s]of Object.entries(n))e in t?t[e]=s:t.setAttribute(e,s)}),r)}),(()=>{alert("Failed to copy command to clipboard")})):alert("Failed to find the code block to copy")}getCookie(e){return document.cookie.split("; ").find((t=>t.startsWith(e+"=")))?.split("=")[1]||null}}class PPHPLocalStore{static instance=null;state;listeners;pphp;STORAGE_KEY;constructor(e={}){this.state=e,this.listeners=[],this.pphp=PPHP.instance,this.STORAGE_KEY=this.pphp.getCookie("pphp_local_store_key")||"pphp_local_store_59e13",this.loadState()}static getInstance(e={}){return PPHPLocalStore.instance||(PPHPLocalStore.instance=new PPHPLocalStore(e)),PPHPLocalStore.instance}setState(e,t=!1){if(this.state={...this.state,...e},this.listeners.forEach((e=>e(this.state))),this.saveState(),t){const e=localStorage.getItem(this.STORAGE_KEY);e&&this.pphp.fetchFunction(this.STORAGE_KEY,{[this.STORAGE_KEY]:e})}}saveState(){localStorage.setItem(this.STORAGE_KEY,JSON.stringify(this.state))}loadState(){const e=localStorage.getItem(this.STORAGE_KEY);e&&(this.state=this.pphp.parseJson(e),this.listeners.forEach((e=>e(this.state))))}resetState(e,t=!1){if(e?(delete this.state[e],this.saveState()):(this.state={},localStorage.removeItem(this.STORAGE_KEY)),this.listeners.forEach((e=>e(this.state))),t){const t=e?localStorage.getItem(this.STORAGE_KEY):null;this.pphp.fetchFunction(this.STORAGE_KEY,{[this.STORAGE_KEY]:t})}}}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 n=this.params;n.set(e,t),this.updateURL(n)}delete(e){const t=this.params;t.delete(e),this.updateURL(t)}replace(e){const t=new URLSearchParams;for(const n in e){const s=e[n];null!==s&&t.set(n,s)}this.updateURL(t,!0)}updateURL(e,t=!1){const n=`${window.location.pathname}?${e.toString()}`;t?history.replaceState(null,"",n):history.pushState(null,"",n),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();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):(global=global||self,global.morphdom=factory())})(this,function(){"use strict";var DOCUMENT_FRAGMENT_NODE=11;function morphAttrs(fromNode,toNode){var toNodeAttrs=toNode.attributes;var attr;var attrName;var attrNamespaceURI;var attrValue;var fromValue;if(toNode.nodeType===DOCUMENT_FRAGMENT_NODE||fromNode.nodeType===DOCUMENT_FRAGMENT_NODE){return}for(var i=toNodeAttrs.length-1;i>=0;i--){attr=toNodeAttrs[i];attrName=attr.name;attrNamespaceURI=attr.namespaceURI;attrValue=attr.value;if(attrNamespaceURI){attrName=attr.localName||attrName;fromValue=fromNode.getAttributeNS(attrNamespaceURI,attrName);if(fromValue!==attrValue){if(attr.prefix==="xmlns"){attrName=attr.name}fromNode.setAttributeNS(attrNamespaceURI,attrName,attrValue)}}else{fromValue=fromNode.getAttribute(attrName);if(fromValue!==attrValue){fromNode.setAttribute(attrName,attrValue)}}}var fromNodeAttrs=fromNode.attributes;for(var d=fromNodeAttrs.length-1;d>=0;d--){attr=fromNodeAttrs[d];attrName=attr.name;attrNamespaceURI=attr.namespaceURI;if(attrNamespaceURI){attrName=attr.localName||attrName;if(!toNode.hasAttributeNS(attrNamespaceURI,attrName)){fromNode.removeAttributeNS(attrNamespaceURI,attrName)}}else{if(!toNode.hasAttribute(attrName)){fromNode.removeAttribute(attrName)}}}}var range;var NS_XHTML="http://www.w3.org/1999/xhtml";var doc=typeof document==="undefined"?undefined:document;var HAS_TEMPLATE_SUPPORT=!!doc&&"content"in doc.createElement("template");var HAS_RANGE_SUPPORT=!!doc&&doc.createRange&&"createContextualFragment"in doc.createRange();function createFragmentFromTemplate(str){var template=doc.createElement("template");template.innerHTML=str;return template.content.childNodes[0]}function createFragmentFromRange(str){if(!range){range=doc.createRange();range.selectNode(doc.body)}var fragment=range.createContextualFragment(str);return fragment.childNodes[0]}function createFragmentFromWrap(str){var fragment=doc.createElement("body");fragment.innerHTML=str;return fragment.childNodes[0]}function toElement(str){str=str.trim();if(HAS_TEMPLATE_SUPPORT){return createFragmentFromTemplate(str)}else if(HAS_RANGE_SUPPORT){return createFragmentFromRange(str)}return createFragmentFromWrap(str)}function compareNodeNames(fromEl,toEl){var fromNodeName=fromEl.nodeName;var toNodeName=toEl.nodeName;var fromCodeStart,toCodeStart;if(fromNodeName===toNodeName){return true}fromCodeStart=fromNodeName.charCodeAt(0);toCodeStart=toNodeName.charCodeAt(0);if(fromCodeStart<=90&&toCodeStart>=97){return fromNodeName===toNodeName.toUpperCase()}else if(toCodeStart<=90&&fromCodeStart>=97){return toNodeName===fromNodeName.toUpperCase()}else{return false}}function createElementNS(name,namespaceURI){return!namespaceURI||namespaceURI===NS_XHTML?doc.createElement(name):doc.createElementNS(namespaceURI,name)}function moveChildren(fromEl,toEl){var curChild=fromEl.firstChild;while(curChild){var nextChild=curChild.nextSibling;toEl.appendChild(curChild);curChild=nextChild}return toEl}function syncBooleanAttrProp(fromEl,toEl,name){if(fromEl[name]!==toEl[name]){fromEl[name]=toEl[name];if(fromEl[name]){fromEl.setAttribute(name,"")}else{fromEl.removeAttribute(name)}}}var specialElHandlers={OPTION:function(fromEl,toEl){var parentNode=fromEl.parentNode;if(parentNode){var parentName=parentNode.nodeName.toUpperCase();if(parentName==="OPTGROUP"){parentNode=parentNode.parentNode;parentName=parentNode&&parentNode.nodeName.toUpperCase()}if(parentName==="SELECT"&&!parentNode.hasAttribute("multiple")){if(fromEl.hasAttribute("selected")&&!toEl.selected){fromEl.setAttribute("selected","selected");fromEl.removeAttribute("selected")}parentNode.selectedIndex=-1}}syncBooleanAttrProp(fromEl,toEl,"selected")},INPUT:function(fromEl,toEl){syncBooleanAttrProp(fromEl,toEl,"checked");syncBooleanAttrProp(fromEl,toEl,"disabled");if(fromEl.value!==toEl.value){fromEl.value=toEl.value}if(!toEl.hasAttribute("value")){fromEl.removeAttribute("value")}},TEXTAREA:function(fromEl,toEl){var newValue=toEl.value;if(fromEl.value!==newValue){fromEl.value=newValue}var firstChild=fromEl.firstChild;if(firstChild){var oldValue=firstChild.nodeValue;if(oldValue==newValue||!newValue&&oldValue==fromEl.placeholder){return}firstChild.nodeValue=newValue}},SELECT:function(fromEl,toEl){if(!toEl.hasAttribute("multiple")){var selectedIndex=-1;var i=0;var curChild=fromEl.firstChild;var optgroup;var nodeName;while(curChild){nodeName=curChild.nodeName&&curChild.nodeName.toUpperCase();if(nodeName==="OPTGROUP"){optgroup=curChild;curChild=optgroup.firstChild}else{if(nodeName==="OPTION"){if(curChild.hasAttribute("selected")){selectedIndex=i;break}i++}curChild=curChild.nextSibling;if(!curChild&&optgroup){curChild=optgroup.nextSibling;optgroup=null}}}fromEl.selectedIndex=selectedIndex}}};var ELEMENT_NODE=1;var DOCUMENT_FRAGMENT_NODE$1=11;var TEXT_NODE=3;var COMMENT_NODE=8;function noop(){}function defaultGetNodeKey(node){if(node){return node.getAttribute&&node.getAttribute("id")||node.id}}function morphdomFactory(morphAttrs){return function morphdom(fromNode,toNode,options){if(!options){options={}}if(typeof toNode==="string"){if(fromNode.nodeName==="#document"||fromNode.nodeName==="HTML"||fromNode.nodeName==="BODY"){var toNodeHtml=toNode;toNode=doc.createElement("html");toNode.innerHTML=toNodeHtml}else{toNode=toElement(toNode)}}else if(toNode.nodeType===DOCUMENT_FRAGMENT_NODE$1){toNode=toNode.firstElementChild}var getNodeKey=options.getNodeKey||defaultGetNodeKey;var onBeforeNodeAdded=options.onBeforeNodeAdded||noop;var onNodeAdded=options.onNodeAdded||noop;var onBeforeElUpdated=options.onBeforeElUpdated||noop;var onElUpdated=options.onElUpdated||noop;var onBeforeNodeDiscarded=options.onBeforeNodeDiscarded||noop;var onNodeDiscarded=options.onNodeDiscarded||noop;var onBeforeElChildrenUpdated=options.onBeforeElChildrenUpdated||noop;var skipFromChildren=options.skipFromChildren||noop;var addChild=options.addChild||function(parent,child){return parent.appendChild(child)};var childrenOnly=options.childrenOnly===true;var fromNodesLookup=Object.create(null);var keyedRemovalList=[];function addKeyedRemoval(key){keyedRemovalList.push(key)}function walkDiscardedChildNodes(node,skipKeyedNodes){if(node.nodeType===ELEMENT_NODE){var curChild=node.firstChild;while(curChild){var key=undefined;if(skipKeyedNodes&&(key=getNodeKey(curChild))){addKeyedRemoval(key)}else{onNodeDiscarded(curChild);if(curChild.firstChild){walkDiscardedChildNodes(curChild,skipKeyedNodes)}}curChild=curChild.nextSibling}}}function removeNode(node,parentNode,skipKeyedNodes){if(onBeforeNodeDiscarded(node)===false){return}if(parentNode){parentNode.removeChild(node)}onNodeDiscarded(node);walkDiscardedChildNodes(node,skipKeyedNodes)}function indexTree(node){if(node.nodeType===ELEMENT_NODE||node.nodeType===DOCUMENT_FRAGMENT_NODE$1){var curChild=node.firstChild;while(curChild){var key=getNodeKey(curChild);if(key){fromNodesLookup[key]=curChild}indexTree(curChild);curChild=curChild.nextSibling}}}indexTree(fromNode);function handleNodeAdded(el){onNodeAdded(el);var curChild=el.firstChild;while(curChild){var nextSibling=curChild.nextSibling;var key=getNodeKey(curChild);if(key){var unmatchedFromEl=fromNodesLookup[key];if(unmatchedFromEl&&compareNodeNames(curChild,unmatchedFromEl)){curChild.parentNode.replaceChild(unmatchedFromEl,curChild);morphEl(unmatchedFromEl,curChild)}else{handleNodeAdded(curChild)}}else{handleNodeAdded(curChild)}curChild=nextSibling}}function cleanupFromEl(fromEl,curFromNodeChild,curFromNodeKey){while(curFromNodeChild){var fromNextSibling=curFromNodeChild.nextSibling;if(curFromNodeKey=getNodeKey(curFromNodeChild)){addKeyedRemoval(curFromNodeKey)}else{removeNode(curFromNodeChild,fromEl,true)}curFromNodeChild=fromNextSibling}}function morphEl(fromEl,toEl,childrenOnly){var toElKey=getNodeKey(toEl);if(toElKey){delete fromNodesLookup[toElKey]}if(!childrenOnly){var beforeUpdateResult=onBeforeElUpdated(fromEl,toEl);if(beforeUpdateResult===false){return}else if(beforeUpdateResult instanceof HTMLElement){fromEl=beforeUpdateResult;indexTree(fromEl)}morphAttrs(fromEl,toEl);onElUpdated(fromEl);if(onBeforeElChildrenUpdated(fromEl,toEl)===false){return}}if(fromEl.nodeName!=="TEXTAREA"){morphChildren(fromEl,toEl)}else{specialElHandlers.TEXTAREA(fromEl,toEl)}}function morphChildren(fromEl,toEl){var skipFrom=skipFromChildren(fromEl,toEl);var curToNodeChild=toEl.firstChild;var curFromNodeChild=fromEl.firstChild;var curToNodeKey;var curFromNodeKey;var fromNextSibling;var toNextSibling;var matchingFromEl;outer:while(curToNodeChild){toNextSibling=curToNodeChild.nextSibling;curToNodeKey=getNodeKey(curToNodeChild);while(!skipFrom&&curFromNodeChild){fromNextSibling=curFromNodeChild.nextSibling;if(curToNodeChild.isSameNode&&curToNodeChild.isSameNode(curFromNodeChild)){curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling;continue outer}curFromNodeKey=getNodeKey(curFromNodeChild);var curFromNodeType=curFromNodeChild.nodeType;var isCompatible=undefined;if(curFromNodeType===curToNodeChild.nodeType){if(curFromNodeType===ELEMENT_NODE){if(curToNodeKey){if(curToNodeKey!==curFromNodeKey){if(matchingFromEl=fromNodesLookup[curToNodeKey]){if(fromNextSibling===matchingFromEl){isCompatible=false}else{fromEl.insertBefore(matchingFromEl,curFromNodeChild);if(curFromNodeKey){addKeyedRemoval(curFromNodeKey)}else{removeNode(curFromNodeChild,fromEl,true)}curFromNodeChild=matchingFromEl;curFromNodeKey=getNodeKey(curFromNodeChild)}}else{isCompatible=false}}}else if(curFromNodeKey){isCompatible=false}isCompatible=isCompatible!==false&&compareNodeNames(curFromNodeChild,curToNodeChild);if(isCompatible){morphEl(curFromNodeChild,curToNodeChild)}}else if(curFromNodeType===TEXT_NODE||curFromNodeType==COMMENT_NODE){isCompatible=true;if(curFromNodeChild.nodeValue!==curToNodeChild.nodeValue){curFromNodeChild.nodeValue=curToNodeChild.nodeValue}}}if(isCompatible){curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling;continue outer}if(curFromNodeKey){addKeyedRemoval(curFromNodeKey)}else{removeNode(curFromNodeChild,fromEl,true)}curFromNodeChild=fromNextSibling}if(curToNodeKey&&(matchingFromEl=fromNodesLookup[curToNodeKey])&&compareNodeNames(matchingFromEl,curToNodeChild)){if(!skipFrom){addChild(fromEl,matchingFromEl)}morphEl(matchingFromEl,curToNodeChild)}else{var onBeforeNodeAddedResult=onBeforeNodeAdded(curToNodeChild);if(onBeforeNodeAddedResult!==false){if(onBeforeNodeAddedResult){curToNodeChild=onBeforeNodeAddedResult}if(curToNodeChild.actualize){curToNodeChild=curToNodeChild.actualize(fromEl.ownerDocument||doc)}addChild(fromEl,curToNodeChild);handleNodeAdded(curToNodeChild)}}curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling}cleanupFromEl(fromEl,curFromNodeChild,curFromNodeKey);var specialElHandler=specialElHandlers[fromEl.nodeName];if(specialElHandler){specialElHandler(fromEl,toEl)}}var morphedNode=fromNode;var morphedNodeType=morphedNode.nodeType;var toNodeType=toNode.nodeType;if(!childrenOnly){if(morphedNodeType===ELEMENT_NODE){if(toNodeType===ELEMENT_NODE){if(!compareNodeNames(fromNode,toNode)){onNodeDiscarded(fromNode);morphedNode=moveChildren(fromNode,createElementNS(toNode.nodeName,toNode.namespaceURI))}}else{morphedNode=toNode}}else if(morphedNodeType===TEXT_NODE||morphedNodeType===COMMENT_NODE){if(toNodeType===morphedNodeType){if(morphedNode.nodeValue!==toNode.nodeValue){morphedNode.nodeValue=toNode.nodeValue}return morphedNode}else{morphedNode=toNode}}}if(morphedNode===toNode){onNodeDiscarded(fromNode)}else{if(toNode.isSameNode&&toNode.isSameNode(morphedNode)){return}morphEl(morphedNode,toNode,childrenOnly);if(keyedRemovalList){for(var i=0,len=keyedRemovalList.length;i<len;i++){var elToRemove=fromNodesLookup[keyedRemovalList[i]];if(elToRemove){removeNode(elToRemove,elToRemove.parentNode,false)}}}}if(!childrenOnly&&morphedNode!==fromNode&&fromNode.parentNode){if(morphedNode.actualize){morphedNode=morphedNode.actualize(fromNode.ownerDocument||doc)}fromNode.parentNode.replaceChild(morphedNode,fromNode)}return morphedNode}}var morphdom=morphdomFactory(morphAttrs);return morphdom});
|