@kirigami/php-prepros 1.1.0 → 1.6.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 +1593 -869
- package/index.d.ts +145 -2
- package/index.js +1 -1
- package/package.json +4 -4
- package/src/imagebatch.php +67 -0
- package/src/libraries/aliases.inc.php +836 -0
- package/src/libraries/curl.class.php +20 -3
- package/src/libraries/fs.class.php +161 -6
- package/src/libraries/html.class.php +92 -22
- package/src/libraries/img.class.php +372 -17
- package/src/libraries/ld.class.php +804 -0
- package/src/libraries/md.class.php +502 -173
- package/src/libraries/md.plugins.php +25 -19
- package/src/libraries/normalizer.class.php +310 -0
- package/src/libraries/prepros.class.php +149 -10
- package/src/libraries/prepros.plugins.php +56 -6
- package/src/libraries/schema.class.php +550 -0
- package/src/libraries/scraper.class.php +64 -59
- package/src/libraries/std.class.php +3 -0
- package/src/libraries/str.class.php +50 -16
- package/src/libraries/yaml.class.php +66 -66
- package/src/phpjs/fstat.js +9 -0
- package/src/prepros.js +126 -47
- package/src/prepros.php +9 -2
- package/src/runenv.php +5 -2
- package/src/utils/getfilestats.js +30 -0
- package/src/utils/isbinary.js +14 -14
- package/src/utils.inc.php +20 -9
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Gets a file's information.
|
|
5
|
+
* @param {string} filePath - the file path
|
|
6
|
+
* @returns {Promise<object>} object holding the file's info
|
|
7
|
+
*/
|
|
8
|
+
async function getFileStats(filePath) {
|
|
9
|
+
try {
|
|
10
|
+
const stats = await stat(filePath);
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
exists: true,
|
|
14
|
+
isFile: stats.isFile(),
|
|
15
|
+
isDirectory: stats.isDirectory(),
|
|
16
|
+
size: stats.size, // in bytes
|
|
17
|
+
createdAt: stats.birthtime,
|
|
18
|
+
modifiedAt: stats.mtime,
|
|
19
|
+
accessedAt: stats.atime,
|
|
20
|
+
changedAt: stats.ctime, // last metadata change
|
|
21
|
+
};
|
|
22
|
+
} catch (error) {
|
|
23
|
+
if (error.code === 'ENOENT') {
|
|
24
|
+
return { exists: false };
|
|
25
|
+
}
|
|
26
|
+
throw error; // other errors (permissions, etc.)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default getFileStats;
|
package/src/utils/isbinary.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// Magic-bytes table compiled once at module load
|
|
2
|
+
// Key = first byte, value = list of signatures [bytes, length to read]
|
|
3
3
|
const MAGIC_MAP = new Map([
|
|
4
4
|
[0x89, [[[0x89, 0x50, 0x4E, 0x47]]]], // PNG
|
|
5
5
|
[0xFF, [[[0xFF, 0xD8, 0xFF]], [[0xFF, 0xFE]]]], // JPEG, UTF-16 LE (text BOM)
|
|
@@ -14,20 +14,20 @@ const MAGIC_MAP = new Map([
|
|
|
14
14
|
[0x00, [[[0x00, 0x00, 0xFE, 0xFF]]]], // UTF-32 BE BOM (text!)
|
|
15
15
|
]);
|
|
16
16
|
|
|
17
|
-
// BOMs
|
|
17
|
+
// Text BOMs → never binary, immediate early exit
|
|
18
18
|
const TEXT_BOMS = new Set([
|
|
19
19
|
'\xEF\xBB\xBF', // UTF-8
|
|
20
20
|
'\xFF\xFE', // UTF-16 LE
|
|
21
21
|
'\xFE\xFF', // UTF-16 BE
|
|
22
22
|
]);
|
|
23
23
|
|
|
24
|
-
const SAMPLE_SIZE = 512; // 8
|
|
24
|
+
const SAMPLE_SIZE = 512; // 8 KB is overkill for a local mount
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* 3-pass binary detection with aggressive early exit.
|
|
28
|
+
* Optimized to be called on hundreds of files at startup.
|
|
29
29
|
*
|
|
30
|
-
* @param {Buffer} buf -
|
|
30
|
+
* @param {Buffer} buf - the file's Buffer (readFileSync)
|
|
31
31
|
* @returns {boolean}
|
|
32
32
|
*/
|
|
33
33
|
function isBinary(buf) {
|
|
@@ -36,16 +36,16 @@ function isBinary(buf) {
|
|
|
36
36
|
|
|
37
37
|
const b0 = buf[0];
|
|
38
38
|
|
|
39
|
-
//
|
|
39
|
+
// Pass 1 — Magic bytes (O(1), max 4 comparisons)
|
|
40
40
|
const candidates = MAGIC_MAP.get(b0);
|
|
41
41
|
if (candidates) {
|
|
42
42
|
for (const sigs of candidates) {
|
|
43
43
|
for (const sig of sigs) {
|
|
44
44
|
if (sig.every((b, i) => buf[i] === b)) {
|
|
45
|
-
// BOM
|
|
45
|
+
// Text BOM → immediate "text" exit
|
|
46
46
|
if (b0 === 0xEF || b0 === 0xFE || (b0 === 0xFF && buf[1] === 0xFE)) return false;
|
|
47
47
|
if (b0 === 0x00 && buf[1] === 0x00) return false; // UTF-32
|
|
48
|
-
return true; //
|
|
48
|
+
return true; // Binary confirmed
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -53,17 +53,17 @@ function isBinary(buf) {
|
|
|
53
53
|
|
|
54
54
|
const sample = Math.min(len, SAMPLE_SIZE);
|
|
55
55
|
|
|
56
|
-
//
|
|
57
|
-
// indexOf
|
|
56
|
+
// Pass 2 — NUL byte (a near-certain binary signal, very common in binaries)
|
|
57
|
+
// indexOf is native C++ → much faster than a JS loop
|
|
58
58
|
if (buf.indexOf(0x00, 0, 'binary') !== -1 &&
|
|
59
59
|
buf.indexOf(0x00) < sample) return true;
|
|
60
60
|
|
|
61
|
-
//
|
|
61
|
+
// Pass 3 — Statistical ratio over the sample
|
|
62
62
|
let nonText = 0;
|
|
63
63
|
for (let i = 0; i < sample; i++) {
|
|
64
64
|
const b = buf[i];
|
|
65
65
|
if (b < 0x20) {
|
|
66
|
-
//
|
|
66
|
+
// Control characters that are legitimate in text
|
|
67
67
|
if (b !== 0x09 && b !== 0x0A && b !== 0x0D && b !== 0x0C && b !== 0x1B) {
|
|
68
68
|
nonText++;
|
|
69
69
|
}
|
package/src/utils.inc.php
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
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
|
-
|
|
9
2
|
|
|
10
3
|
const BR = '<br>';
|
|
11
4
|
const RN = "\r\n";
|
|
@@ -14,35 +7,53 @@ const R = "\r";
|
|
|
14
7
|
const N = "\n";
|
|
15
8
|
|
|
16
9
|
|
|
17
|
-
function _print_r(mixed $obj) {
|
|
10
|
+
function _print_r(mixed $obj, bool $ret = false) {
|
|
11
|
+
if($ret) return '<pre>' . print_r($obj, $ret) . '</pre>';
|
|
18
12
|
echo '<pre>' . print_r($obj, true) . '</pre>';
|
|
19
13
|
}
|
|
20
14
|
|
|
21
15
|
|
|
22
16
|
spl_autoload_register(function ($class) {
|
|
23
17
|
static $catalog = [
|
|
18
|
+
|
|
19
|
+
// Out of the box
|
|
24
20
|
'ARR' => 'arr.class.php',
|
|
25
21
|
'CACHE' => 'cache.class.php',
|
|
26
22
|
'CURL' => 'curl.class.php',
|
|
27
23
|
'FS' => 'fs.class.php',
|
|
28
24
|
'HTML' => 'html.class.php',
|
|
29
25
|
'IMG' => 'img.class.php',
|
|
26
|
+
'LD' => 'ld.class.php',
|
|
30
27
|
'MD' => 'md.class.php',
|
|
28
|
+
'NORM' => 'norm.class.php',
|
|
31
29
|
'OBF' => 'obf.class.php',
|
|
32
30
|
'PREPROS' => 'prepros.class.php',
|
|
31
|
+
'SCHEMA' => 'schema.class.php',
|
|
33
32
|
'SCRAPER' => 'scraper.class.php',
|
|
34
33
|
'STD' => 'std.class.php',
|
|
35
34
|
'STR' => 'str.class.php',
|
|
36
35
|
'YAML' => 'yaml.class.php',
|
|
36
|
+
|
|
37
|
+
// Fallbacks
|
|
38
|
+
'Normalizer' => 'normalizer.class.php'
|
|
37
39
|
];
|
|
38
40
|
if (isset($catalog[$class])) require_once(__DIR__ . '/libraries/' . $catalog[$class]);
|
|
39
41
|
}, true, true);
|
|
40
42
|
|
|
41
43
|
|
|
44
|
+
|
|
42
45
|
$argv = array_merge(['prepros.php'], json_decode(getenv('PREPROS_ARGS'), true));
|
|
43
46
|
$config = json_decode(getenv('PREPROS_CONFIG'));
|
|
44
47
|
date_default_timezone_set($config->timezone);
|
|
45
48
|
chdir('/project');
|
|
46
49
|
|
|
50
|
+
require_once(__DIR__ . '/libraries/aliases.inc.php');
|
|
51
|
+
|
|
52
|
+
PREPROS::loadConfig($config);
|
|
47
53
|
|
|
48
|
-
|
|
54
|
+
// Bootstrap is done: config loaded, `includes` pulled in, aliases available.
|
|
55
|
+
// Fires once per process, before any page renders, for every entrypoint
|
|
56
|
+
// (prepros.php, runenv.php, imagebatch.php). A plugin registered from an
|
|
57
|
+
// `includes` file (or prepros.plugins.php) can hook here to pull in extra
|
|
58
|
+
// PHP files or wire itself up.
|
|
59
|
+
PREPROS::runHook('boot', $config);
|