@kirigami/php-prepros 1.0.9 → 1.1.0
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/README.md +300 -59
- package/index.js +1 -1
- package/package.json +4 -3
- package/src/libraries/arr.class.php +29 -0
- package/src/libraries/cache.class.php +5 -4
- package/src/libraries/curl.class.php +106 -0
- package/src/libraries/html.class.php +2 -0
- package/src/libraries/img.class.php +1 -1
- package/src/libraries/prepros.class.php +22 -3
- package/src/libraries/scraper.class.php +320 -0
- package/src/libraries/std.class.php +6 -2
- package/src/libraries/str.class.php +34 -0
- package/src/phpjs/mount.js +28 -0
- package/src/prepros.js +93 -24
- package/src/prepros.php +4 -17
- package/src/runenv.php +17 -0
- package/src/utils/findfile.js +25 -0
- package/src/utils.inc.php +21 -2
package/src/prepros.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
import path, { dirname } from "path";
|
|
3
2
|
import isBinary from './utils/isbinary.js';
|
|
4
3
|
import joinWith from './utils/joinwith.js'
|
|
4
|
+
import path, { dirname } from "path";
|
|
5
5
|
import { spawn } from 'child_process';
|
|
6
|
-
import { fileURLToPath } from
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
7
7
|
import { walkFile } from '@kirigami/struct-walker';
|
|
8
8
|
import { getPHPRuntime, getPHPRuntimeWithNetwork } from "@kirigami/php-wasm";
|
|
9
9
|
|
|
@@ -20,13 +20,14 @@ const config = await walkFile(__configpath);
|
|
|
20
20
|
if(!config) throw `Invalid config file: ${__configpath}`;
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
|
|
23
24
|
const getPHPInstance = async () => {
|
|
24
25
|
if(!__php) {
|
|
25
26
|
if(config?.kirigami?.root === undefined) throw `Missing prepros:root property in config file: ${__configpath}`;
|
|
26
27
|
__root = path.join(__project, config.kirigami.root);
|
|
27
28
|
if (!fs.existsSync(__root)) throw `Invalid prepros:root path: ${__root}`;
|
|
28
29
|
|
|
29
|
-
const preprosConfig = config.prepros;
|
|
30
|
+
const preprosConfig = config.prepros || {};
|
|
30
31
|
preprosConfig.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
31
32
|
preprosConfig.root = joinWith('/project/', config?.kirigami?.root);
|
|
32
33
|
preprosConfig.data = config.kirigami || {};
|
|
@@ -35,21 +36,49 @@ const getPHPInstance = async () => {
|
|
|
35
36
|
__php.setSpawnHandler((command, args, options) => spawn(command, args, options));
|
|
36
37
|
__php.preprosConfig = preprosConfig;
|
|
37
38
|
|
|
38
|
-
const mountPaths = [];
|
|
39
39
|
const __cache = path.join(__project, '.cache.db');
|
|
40
|
+
const __cookie = path.join(__project, '.cookie.txt');
|
|
40
41
|
mountPath(__php, __dirname, '/prepros');
|
|
41
42
|
mountPath(__php, joinWith(__project, config?.kirigami?.root), joinWith('/project', config?.kirigami?.root));
|
|
43
|
+
|
|
42
44
|
if (fs.existsSync(__cache)) mountPath(__php, __cache, '/project/.cache.db');
|
|
45
|
+
if (fs.existsSync(__cookie)) mountPath(__php, __cookie, '/project/.cookie.txt');
|
|
46
|
+
|
|
47
|
+
__php.onMessage(async (data) => {
|
|
48
|
+
const msg = JSON.parse(data);
|
|
49
|
+
if(!msg.command) return { success: false, error: "Invalid command."};
|
|
50
|
+
const file = path.join(__dirname, 'phpjs', `${msg.command}.js`);
|
|
51
|
+
if(!fs.existsSync(file)) return { success: false, error: "Invalid command."};
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const cmdModule = await import(pathToFileURL(file).href);
|
|
55
|
+
const results = await cmdModule.default(__php, msg);
|
|
56
|
+
return JSON.stringify({
|
|
57
|
+
success: true,
|
|
58
|
+
results: results
|
|
59
|
+
});
|
|
60
|
+
} catch(e) {
|
|
61
|
+
return {
|
|
62
|
+
success: false,
|
|
63
|
+
error: typeof e == 'string' ? e : e.message
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
// console.log(msg);
|
|
69
|
+
// console.log(__dirname);
|
|
70
|
+
|
|
71
|
+
});
|
|
43
72
|
}
|
|
44
73
|
return __php;
|
|
45
74
|
}
|
|
46
75
|
|
|
47
76
|
|
|
48
77
|
const mountPath = (php, localPath, virtualDir) => {
|
|
49
|
-
const includeExtensions = new Set(['.php', '.json', '.yaml', '.md', '.db', ...(config?.prepros?.mountext || [])]);
|
|
78
|
+
const includeExtensions = new Set(['.php', '.json', '.yaml', '.yml', '.md', '.db', '.txt', ...(config?.prepros?.mountext || [])]);
|
|
50
79
|
const stat = fs.statSync(localPath);
|
|
51
80
|
if (stat.isDirectory()) {
|
|
52
|
-
php.
|
|
81
|
+
php.mkdirTree(virtualDir);
|
|
53
82
|
for (const entry of fs.readdirSync(localPath, { withFileTypes: true })) {
|
|
54
83
|
mountPath(php, path.join(localPath, entry.name), virtualDir + '/' + entry.name);
|
|
55
84
|
}
|
|
@@ -57,46 +86,86 @@ const mountPath = (php, localPath, virtualDir) => {
|
|
|
57
86
|
const ext = path.extname(localPath).toLowerCase();
|
|
58
87
|
if (includeExtensions.has(ext)) {
|
|
59
88
|
const buf = fs.readFileSync(localPath);
|
|
89
|
+
const parentDir = virtualDir.substring(0, virtualDir.lastIndexOf('/'));
|
|
90
|
+
if (parentDir) {
|
|
91
|
+
php.mkdirTree(parentDir);
|
|
92
|
+
}
|
|
60
93
|
php.writeFile(virtualDir, isBinary(buf) ? buf : buf.toString('utf8'));
|
|
61
94
|
}
|
|
62
95
|
}
|
|
63
96
|
}
|
|
64
97
|
|
|
65
98
|
|
|
66
|
-
const run = async (args) => {
|
|
99
|
+
const run = async (args = [], script = null, mountfiles = []) => {
|
|
67
100
|
const php = await getPHPInstance();
|
|
101
|
+
|
|
102
|
+
await Promise.all(mountfiles.map(async item => {
|
|
103
|
+
const file = path.resolve(item);
|
|
104
|
+
if(!fs.existsSync(file)) return;
|
|
105
|
+
if(!path.relative(__project, file)) return;
|
|
106
|
+
const dest = path.join('/project', file.replace(__project, '')).replaceAll('\\', '/');
|
|
107
|
+
const buf = fs.readFileSync(file);
|
|
108
|
+
const parentDir = dest.substring(0, dest.lastIndexOf('/'));
|
|
109
|
+
if (parentDir) php.mkdirTree(parentDir);
|
|
110
|
+
php.writeFile(dest, isBinary(buf) ? buf : buf.toString('utf8'));
|
|
111
|
+
}));
|
|
112
|
+
|
|
68
113
|
const output = await php.runStream({
|
|
69
|
-
scriptPath: '/prepros/prepros.php',
|
|
114
|
+
scriptPath: script || '/prepros/prepros.php',
|
|
70
115
|
env: {
|
|
71
|
-
PREPROS_ARGS:
|
|
116
|
+
PREPROS_ARGS: JSON.stringify(args),
|
|
72
117
|
PREPROS_CONFIG: JSON.stringify(php.preprosConfig)
|
|
73
118
|
}
|
|
74
119
|
});
|
|
120
|
+
|
|
75
121
|
const stdout = await output.stdoutText;
|
|
76
122
|
const stderr = await output.stderrText;
|
|
123
|
+
|
|
77
124
|
let retobj;
|
|
125
|
+
const resultPath = '/internal/prepros_result.json';
|
|
126
|
+
|
|
78
127
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
128
|
+
if (await php.fileExists(resultPath)) {
|
|
129
|
+
const buffer = php.readFileAsBuffer(resultPath);
|
|
130
|
+
retobj = JSON.parse(Buffer.from(buffer).toString('utf8'));
|
|
131
|
+
retobj.debug = stdout;
|
|
132
|
+
|
|
133
|
+
if(retobj.files) await Promise.all(retobj.files.map(async (file, i) => {
|
|
134
|
+
const fbuffer = php.readFileAsBuffer(file);
|
|
135
|
+
const dest = file.replace(/^\/project\//i, '');
|
|
136
|
+
const dir = dirname(path.join(__project, dest));
|
|
137
|
+
if(!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
138
|
+
fs.writeFileSync(path.join(__project, dest), fbuffer);
|
|
139
|
+
retobj.files[i] = dest;
|
|
140
|
+
}));
|
|
141
|
+
} else {
|
|
142
|
+
retobj = { success: true, files: [], debug: stdout };
|
|
143
|
+
}
|
|
144
|
+
} catch (e) {
|
|
145
|
+
retobj = { success: false, error: 'Response parsing error.' + e, debug: stdout, stderr };
|
|
146
|
+
} finally {
|
|
147
|
+
if (await php.fileExists(resultPath)) {
|
|
148
|
+
await php.unlink(resultPath);
|
|
149
|
+
}
|
|
88
150
|
}
|
|
89
151
|
if (stderr) {
|
|
90
|
-
|
|
91
|
-
retobj = JSON.parse(stderr);
|
|
92
|
-
} catch(e) {
|
|
93
|
-
retobj = { success: false, error: stderr };
|
|
94
|
-
}
|
|
152
|
+
retobj = { success: false, error: stderr, debug: stdout };
|
|
95
153
|
}
|
|
154
|
+
|
|
96
155
|
return retobj;
|
|
97
156
|
}
|
|
98
157
|
|
|
99
158
|
|
|
159
|
+
const runenv = async (script, paths = [], ...args) => {
|
|
160
|
+
if(!script) throw "Missing PHP file.";
|
|
161
|
+
const file = path.resolve(script);
|
|
162
|
+
if(!path.relative(__project, file)) throw "PHP file outside project";
|
|
163
|
+
if(!fs.existsSync(file)) throw "Can't find PHP file";
|
|
164
|
+
const dest = path.join('/project', file.replace(__project, '')).replaceAll('\\', '/');
|
|
165
|
+
return run([dest, ...args], '/prepros/runenv.php', [file, ...paths]);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
|
|
100
169
|
const render = async (file = '.') => {
|
|
101
170
|
const php = await getPHPInstance();
|
|
102
171
|
const target = path.resolve(__project, config?.kirigami?.root, file);
|
|
@@ -123,4 +192,4 @@ const sitemap = async (dir) => {
|
|
|
123
192
|
}
|
|
124
193
|
|
|
125
194
|
|
|
126
|
-
export { render, sitemap };
|
|
195
|
+
export { runenv, render, sitemap };
|
package/src/prepros.php
CHANGED
|
@@ -1,23 +1,10 @@
|
|
|
1
1
|
<?php
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
ini_set('html_errors', 0);
|
|
5
|
-
ini_set('display_errors', 1);
|
|
6
|
-
ini_set('error_reporting', 32767);
|
|
7
|
-
ini_set('error_log', 'php://stderr');
|
|
8
|
-
error_reporting(E_ALL);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
$argv = array_merge(['prepros.php'], json_decode(getenv('PREPROS_ARGS'), true));
|
|
12
|
-
$config = json_decode(getenv('PREPROS_CONFIG'));
|
|
13
|
-
|
|
3
|
+
include(__DIR__ . '/utils.inc.php');
|
|
14
4
|
|
|
15
5
|
try {
|
|
16
|
-
|
|
17
|
-
date_default_timezone_set($config->timezone);
|
|
18
6
|
if (!isset($argv[1])) STD::error("Invalid argument.");
|
|
19
|
-
|
|
20
|
-
PREPROS::loadConfig($config);
|
|
7
|
+
|
|
21
8
|
if($argv[1] == 'sitemap') {
|
|
22
9
|
if(!PREPROS::sitemap()) STD::error("Can't produce the sitemap.");
|
|
23
10
|
STD::succeed(['files' => PREPROS::getExportedFiles()]);
|
|
@@ -38,8 +25,8 @@ try {
|
|
|
38
25
|
}
|
|
39
26
|
|
|
40
27
|
} catch(Exception $e) {
|
|
41
|
-
STD::error($e->getMessage());
|
|
28
|
+
STD::error(['message' => $e->getMessage()]);
|
|
42
29
|
}
|
|
43
30
|
|
|
44
31
|
|
|
45
|
-
STD::succeed(
|
|
32
|
+
STD::succeed();
|
package/src/runenv.php
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
include(__DIR__ . '/utils.inc.php');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
|
|
8
|
+
if (!isset($argv[1])) STD::error("Invalid PHP file.");
|
|
9
|
+
if (!is_file($argv[1])) STD::error("PHP file not found.");
|
|
10
|
+
|
|
11
|
+
require_once($argv[1]);
|
|
12
|
+
|
|
13
|
+
} catch(Exception $e) {
|
|
14
|
+
STD::error($e->getMessage());
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
STD::succeed(['files' => PREPROS::getExportedFiles()]);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from "path";
|
|
3
|
+
import picomatch from "picomatch";
|
|
4
|
+
|
|
5
|
+
export default function findFiles(pattern, cwd = process.cwd()) {
|
|
6
|
+
const isMatch = picomatch(pattern);
|
|
7
|
+
const results = [];
|
|
8
|
+
function walk(dir) {
|
|
9
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
10
|
+
for (const entry of entries) {
|
|
11
|
+
const fullPath = path.join(dir, entry.name);
|
|
12
|
+
const relativePath = path.relative(cwd, fullPath);
|
|
13
|
+
if (entry.isDirectory()) {
|
|
14
|
+
if (entry.name === 'node_modules' || entry.name === '.git') continue;
|
|
15
|
+
walk(fullPath);
|
|
16
|
+
} else if (entry.isFile()) {
|
|
17
|
+
if (isMatch(relativePath.split(path.sep).join('/'))) {
|
|
18
|
+
results.push(relativePath.replaceAll('\\', '/'));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
walk(cwd);
|
|
24
|
+
return results;
|
|
25
|
+
}
|
package/src/utils.inc.php
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
<?php
|
|
2
|
+
ini_set('log_errors', 1);
|
|
3
|
+
ini_set('html_errors', 0);
|
|
4
|
+
ini_set('display_errors', 1);
|
|
5
|
+
ini_set('error_reporting', 32767);
|
|
6
|
+
ini_set('error_log', 'php://stderr');
|
|
7
|
+
error_reporting(E_ALL);
|
|
8
|
+
|
|
2
9
|
|
|
3
10
|
const BR = '<br>';
|
|
4
11
|
const RN = "\r\n";
|
|
@@ -14,16 +21,28 @@ function _print_r(mixed $obj) {
|
|
|
14
21
|
|
|
15
22
|
spl_autoload_register(function ($class) {
|
|
16
23
|
static $catalog = [
|
|
24
|
+
'ARR' => 'arr.class.php',
|
|
17
25
|
'CACHE' => 'cache.class.php',
|
|
26
|
+
'CURL' => 'curl.class.php',
|
|
18
27
|
'FS' => 'fs.class.php',
|
|
19
28
|
'HTML' => 'html.class.php',
|
|
20
29
|
'IMG' => 'img.class.php',
|
|
21
30
|
'MD' => 'md.class.php',
|
|
22
31
|
'OBF' => 'obf.class.php',
|
|
23
32
|
'PREPROS' => 'prepros.class.php',
|
|
24
|
-
'
|
|
33
|
+
'SCRAPER' => 'scraper.class.php',
|
|
34
|
+
'STD' => 'std.class.php',
|
|
25
35
|
'STR' => 'str.class.php',
|
|
26
36
|
'YAML' => 'yaml.class.php',
|
|
27
37
|
];
|
|
28
38
|
if (isset($catalog[$class])) require_once(__DIR__ . '/libraries/' . $catalog[$class]);
|
|
29
|
-
}, true, true);
|
|
39
|
+
}, true, true);
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
$argv = array_merge(['prepros.php'], json_decode(getenv('PREPROS_ARGS'), true));
|
|
43
|
+
$config = json_decode(getenv('PREPROS_CONFIG'));
|
|
44
|
+
date_default_timezone_set($config->timezone);
|
|
45
|
+
chdir('/project');
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
PREPROS::loadConfig($config);
|