@kirigami/php-prepros 1.0.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/LICENSE +21 -0
- package/README.md +622 -0
- package/index.d.ts +109 -0
- package/index.js +1 -0
- package/package.json +58 -0
- package/src/libraries/cache.class.php +101 -0
- package/src/libraries/fs.class.php +133 -0
- package/src/libraries/html.class.php +176 -0
- package/src/libraries/img.class.php +122 -0
- package/src/libraries/md.class.php +444 -0
- package/src/libraries/md.plugins.php +86 -0
- package/src/libraries/obf.class.php +23 -0
- package/src/libraries/prepros.class.php +157 -0
- package/src/libraries/prepros.plugins.php +28 -0
- package/src/libraries/std.class.php +28 -0
- package/src/libraries/str.class.php +47 -0
- package/src/libraries/yaml.class.php +453 -0
- package/src/prepros.js +107 -0
- package/src/prepros.php +45 -0
- package/src/utils/isbinary.js +79 -0
- package/src/utils/joinwith.js +12 -0
- package/src/utils.inc.php +29 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
final class PREPROS
|
|
5
|
+
{
|
|
6
|
+
|
|
7
|
+
public static mixed $config;
|
|
8
|
+
private static string $root;
|
|
9
|
+
private static array $files = [];
|
|
10
|
+
private static array $hooks = [];
|
|
11
|
+
private static array $tags = [];
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
public static function loadConfig(object $config)
|
|
15
|
+
{
|
|
16
|
+
self::$config = $config;
|
|
17
|
+
self::$root = realpath($config->root) . S;
|
|
18
|
+
if (!empty($config->includes)) foreach ($config->includes as $path) {
|
|
19
|
+
if (!is_file(realpath(self::$root . $path))) continue;
|
|
20
|
+
else include_once(realpath(self::$root . $path));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
public static function render(string $file)
|
|
26
|
+
{
|
|
27
|
+
$dir = pathinfo($file, PATHINFO_DIRNAME) . S;
|
|
28
|
+
$target = $dir . ltrim(pathinfo($file, PATHINFO_FILENAME), '_') . '.html';
|
|
29
|
+
$file = realpath($file);
|
|
30
|
+
$absurl = str_replace('//', '/', str_replace('\\', '/', pathinfo(str_replace(realpath(self::$root), '', $file), PATHINFO_DIRNAME)) . '/');
|
|
31
|
+
$relroot = FS::getRelativePath($dir, self::$root);
|
|
32
|
+
$page = self::processHook('page_info', [$file, FS::phpFileInfo($file)]);
|
|
33
|
+
|
|
34
|
+
extract((array)self::$config->data);
|
|
35
|
+
extract((array)$page);
|
|
36
|
+
|
|
37
|
+
self::processHook('pre_render', file_get_contents($file));
|
|
38
|
+
|
|
39
|
+
ob_start();
|
|
40
|
+
if (self::$config->before) include(realpath(self::$root . self::$config->before));
|
|
41
|
+
$header = ob_get_clean();
|
|
42
|
+
|
|
43
|
+
if(empty($content)) {
|
|
44
|
+
ob_start();
|
|
45
|
+
include($file);
|
|
46
|
+
$body = ob_get_clean();
|
|
47
|
+
} else $body = $content;
|
|
48
|
+
|
|
49
|
+
if (!empty($indent)) {
|
|
50
|
+
$body = join(PHP_EOL, array_map(function ($line) use ($indent) {
|
|
51
|
+
return str_repeat(' ', $indent) . $line;
|
|
52
|
+
}, explode(PHP_EOL, $body)));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
ob_start();
|
|
56
|
+
if (self::$config->after) include(realpath(self::$root . self::$config->after));
|
|
57
|
+
$footer = ob_get_clean();
|
|
58
|
+
|
|
59
|
+
$contents = $header . $body . $footer;
|
|
60
|
+
$contents = self::processTags($contents);
|
|
61
|
+
$contents = self::processHook('post_render', $contents);
|
|
62
|
+
|
|
63
|
+
if(!empty(self::$config->format)) $contents = HTML::format($contents);
|
|
64
|
+
|
|
65
|
+
file_put_contents($target, $contents);
|
|
66
|
+
self::exportFile($target);
|
|
67
|
+
return realpath($target);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
public static function sitemap()
|
|
72
|
+
{
|
|
73
|
+
$paths = [];
|
|
74
|
+
$root = realpath(self::$root);
|
|
75
|
+
foreach (FS::dig($root . '/_index.php') as $file) {
|
|
76
|
+
$parent = pathinfo(pathinfo($file, PATHINFO_DIRNAME), PATHINFO_BASENAME);
|
|
77
|
+
if (strpos($parent, '_') === 0) continue;
|
|
78
|
+
if (strpos(pathinfo($file, PATHINFO_FILENAME), '_') !== 0) continue;
|
|
79
|
+
$paths[] = str_replace('\\', '/', ltrim(str_replace($root, '', pathinfo(realpath($file), PATHINFO_DIRNAME)), DIRECTORY_SEPARATOR));
|
|
80
|
+
}
|
|
81
|
+
if (empty($paths)) $paths[] = '';
|
|
82
|
+
$dom = new DOMDocument('1.0', 'UTF-8');
|
|
83
|
+
$dom->formatOutput = true;
|
|
84
|
+
$urlset = $dom->createElementNS('http://www.sitemaps.org/schemas/sitemap/0.9', 'urlset');
|
|
85
|
+
$dom->appendChild($urlset);
|
|
86
|
+
|
|
87
|
+
foreach ($paths as $path) {
|
|
88
|
+
$deep = $path ? count(explode('/', $path)) : 0;
|
|
89
|
+
$priority = sprintf('%0.1f', (10 - $deep) / 10);
|
|
90
|
+
$url = rtrim(self::$config->data->baseurl, '/') . '/' . ltrim(($path ? $path . '/' : ''), '/');
|
|
91
|
+
|
|
92
|
+
$durl = $dom->createElement('url');
|
|
93
|
+
$urlset->appendChild($durl);
|
|
94
|
+
|
|
95
|
+
$durl->appendChild($dom->createElement('loc', $url));
|
|
96
|
+
$durl->appendChild($dom->createElement('lastmod', date('Y-m-d')));
|
|
97
|
+
$durl->appendChild($dom->createElement('changefreq', 'weekly'));
|
|
98
|
+
$durl->appendChild($dom->createElement('priority', $priority));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
$dest = self::$root . 'sitemap.xml';
|
|
102
|
+
file_put_contents($dest, $dom->saveXML());
|
|
103
|
+
self::exportFile($dest);
|
|
104
|
+
return realpath($dest);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
public static function exportFile(string $file): void
|
|
109
|
+
{
|
|
110
|
+
if (!$path = realpath($file)) return;
|
|
111
|
+
self::$files[] = $path;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
public static function getExportedFiles(): array
|
|
116
|
+
{
|
|
117
|
+
$files = array_unique(self::$files);
|
|
118
|
+
sort($files);
|
|
119
|
+
return $files;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
public static function registerHook(string $hook, callable $clb)
|
|
124
|
+
{
|
|
125
|
+
self::$hooks[$hook][] = $clb;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
private static function processHook(string $hook, $data = null)
|
|
130
|
+
{
|
|
131
|
+
if (!empty(self::$hooks[$hook])) {
|
|
132
|
+
foreach (self::$hooks[$hook] as $clb) {
|
|
133
|
+
$data = call_user_func($clb, $data);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return $data;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
public static function registerTag(string $tag, callable $clb)
|
|
141
|
+
{
|
|
142
|
+
self::$tags[$tag] = $clb;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
private static function processTags(string $contents)
|
|
147
|
+
{
|
|
148
|
+
foreach (self::$tags as $tag => $clb) {
|
|
149
|
+
$contents = STR::replaceTags($tag, $contents, $clb);
|
|
150
|
+
}
|
|
151
|
+
return $contents;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
include_once(__DIR__ . '/prepros.plugins.php');
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
PREPROS::registerTag('markdown', function ($tag, $attrs, $body) {
|
|
5
|
+
$body = STR::trimIndent($body);
|
|
6
|
+
return MD::toHtml($body);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
PREPROS::registerHook('page_info', function($info) {
|
|
11
|
+
list($file, $page) = $info;
|
|
12
|
+
foreach($page as $k => $v) {
|
|
13
|
+
$ext = strtolower(pathinfo($v, PATHINFO_EXTENSION));
|
|
14
|
+
if(in_array($ext, ['yaml', 'yml', 'json', 'md']) ) {
|
|
15
|
+
if(preg_match('#^https?:#i', $v)) $filename = $v;
|
|
16
|
+
else $filename = pathinfo(realpath($file), PATHINFO_DIRNAME) . '/' . $v;
|
|
17
|
+
if(is_file($filename) || preg_match('#^https?:#i', $v)) {
|
|
18
|
+
$page->{$k} = match ($ext) {
|
|
19
|
+
'yml', 'yaml' => YAML::parseFile($filename),
|
|
20
|
+
'json' => json_decode(file_get_contents($filename)),
|
|
21
|
+
'md' => MD::toHtml(file_get_contents($filename)),
|
|
22
|
+
default => $filename,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return $page;
|
|
28
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
class STD {
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
public static function succeed($props = []): void
|
|
7
|
+
{
|
|
8
|
+
$return = new stdClass;
|
|
9
|
+
$return->success = true;
|
|
10
|
+
if(is_string($props)) $return->message = $props;
|
|
11
|
+
else foreach($props as $k => $v) $return->{$k} = $v;
|
|
12
|
+
file_put_contents('php://stdout', json_encode($return, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), FILE_APPEND);
|
|
13
|
+
exit(0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
public static function error($props = []): void
|
|
18
|
+
{
|
|
19
|
+
$return = new stdClass;
|
|
20
|
+
$return->success = false;
|
|
21
|
+
if(is_string($props)) $return->error = $props;
|
|
22
|
+
else foreach($props as $k => $v) $return->{$k} = $v;
|
|
23
|
+
file_put_contents('php://stderr', json_encode($return, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), FILE_APPEND);
|
|
24
|
+
exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
class STR
|
|
4
|
+
{
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
public static function htmlesc(string $str): string
|
|
8
|
+
{
|
|
9
|
+
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
public static function replaceTags(string $tag, string $contents, callable $clb): string
|
|
14
|
+
{
|
|
15
|
+
$contents = preg_replace_callback('#<' . preg_quote($tag, '#') . '([^>]*)>(.*?)</' . preg_quote($tag, '#') . '>#msi', function ($m) use ($clb) {
|
|
16
|
+
return call_user_func($clb, $m[0], self::parseHtmlAttributes($m[1]), $m[2]);
|
|
17
|
+
}, $contents);
|
|
18
|
+
return $contents;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
public static function parseHtmlAttributes(string $attributes): array
|
|
23
|
+
{
|
|
24
|
+
if (preg_match_all('#(\\w+)\s*=\\s*("[^"]*"|\'[^\']*\'|[^"\'\\s>]*)#i', $attributes, $m)) {
|
|
25
|
+
foreach ($m[1] as $k => $key) {
|
|
26
|
+
$attrs[strtolower($key)] = stripslashes(substr($m[2][$k], 1, -1));;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return isset($attrs) ? $attrs : [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
public static function trimIndent(string $str): string
|
|
34
|
+
{
|
|
35
|
+
$lines = explode("\n", $str);
|
|
36
|
+
$minIndent = PHP_INT_MAX;
|
|
37
|
+
foreach ($lines as $line) {
|
|
38
|
+
if (trim($line) === '') continue;
|
|
39
|
+
preg_match('/^(\s*)/', $line, $m);
|
|
40
|
+
$minIndent = min($minIndent, strlen($m[1]));
|
|
41
|
+
}
|
|
42
|
+
if ($minIndent > 0 && $minIndent !== PHP_INT_MAX) {
|
|
43
|
+
$lines = array_map(fn($line) => substr($line, $minIndent), $lines);
|
|
44
|
+
}
|
|
45
|
+
return implode("\n", $lines);
|
|
46
|
+
}
|
|
47
|
+
}
|