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