dark mode
[pharext/replicator.pharext.org] / public / html.php
1 <?php
2 const INCLUDED = __FILE__;
3 const NCURRENT = 2;
4
5 $css = "concise/css/concise.min.css";
6 $fnt = "//fonts.googleapis.com/css?family=Droid+Sans";
7
8 require_once "index.php";
9
10 ob_start($res);
11 $res->addHeader("Link", "<" . dirname((new http\Env\Url)->path) . "/" . $css . ">; rel=preload; as=style");
12
13 ?>
14 <!doctype html>
15 <html>
16 <head>
17 <meta charset="utf-8">
18 <title>Replicator</title>
19 <link rel="stylesheet" href="<?=$css?>">
20 <link rel="stylesheet" href="<?=$fnt?>">
21 <meta name="viewport" content="width=device-width, initial-scale=1">
22 <meta name="color-scheme" content="dark light">
23 <style>
24 body {
25 padding-bottom: 2em;
26 padding-top: 7em;
27 }
28 .header {
29 top: 0;
30 width: 100%;
31 }
32 .footer {
33 bottom: 0;
34 width: 100%;
35 text-align: center;
36 font-size: .9em;
37 }
38 .header, .footer {
39 position: fixed;
40 padding: .5em 0;
41 }
42 .header h1 {
43 font-weight: bold;
44 line-height:120%;
45 }
46 .header h1 a, .footer a:hover {
47 text-decoration: none;
48 }
49 .header h1 a:hover {
50 text-decoration: underline;
51 }
52 .header h1 a {
53 /* normalize browser difference */
54 font-size: 1.3em;
55 }
56 .header h1 small {
57 font-size: 1.3rem;
58 }
59 li {
60 list-style-type: circle;
61 }
62 pre.publickey {
63 font-size: .8rem;
64 line-height: 1rem;
65 }
66 pre.code {
67 background: #333;
68 color: #62B3E7;
69 padding: 0 1.5em 1.5em 1em;
70 border-radius: 4px;
71 margin-right: 2em;
72 display: inline-block;
73 }
74 pre.code>code {
75 font-size: .9rem;
76 }
77 .row>h3 {
78 margin-bottom: 0;
79 }
80 hr {
81 margin: 2em 0;
82 }
83 @media(max-width: 80em) {
84 .column-8 {
85 float: none;
86 width: auto;
87 }
88 }
89 .old-version, #new-toggle {
90 display: none;
91 }
92 p.package-description, div.package-description p {
93 white-space: pre-line;
94 }
95 .package-list {
96 }
97 .package-ch {
98 }
99 form * {
100 display: inline-block;
101 margin-right: 1em;
102 }
103 form label input{
104 margin-left: 1em;
105 vertical-align: middle;
106 }
107 form input[type=reset] {
108 padding: 0;
109 }
110 .header, .footer {
111 box-shadow: 0px 0px .8em .4em #89a;
112 background: #62B3E7;
113 }
114 .header h1 a, .footer, .footer a {
115 color: #fdfdfd;
116 text-shadow: grey 0 0 .1em;
117 }
118 .header h1 small {
119 color: #666;
120 text-shadow: white 0 0 .2em;
121 }
122 @media (prefers-color-scheme: dark) {
123 .header, .footer {
124 box-shadow: 0px 0px .8em .4em #123;
125 background: #305872;
126 }
127 .header h1 a, .footer, .footer a {
128 color: #bdbdbd;
129 text-shadow: dimgrey 0 0 .1em;
130 }
131 .header h1 small {
132 color: #aaa;
133 text-shadow: black 0 0 .2em;
134 }
135 body, h2, h3, h4, h5, h6 {
136 background: #3a3b3f;
137 color: #bdbdbd;
138 }
139 }
140 </style>
141 </head>
142 <body>
143 <div class="header">
144 <header>
145 <h1 class="container">
146 <a href="?">Replicator</a><br>
147 <small>Replicating PECL releases as pharext packages since 2015</small>
148 </h1>
149 <a href="https://github.com/m6w6/replicator"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a>
150 </header>
151 </div>
152 <div class="container">
153
154 <?php if (!empty($package)) : $versions = package_versions($package); $info = package_info($package); ?>
155
156 <h2><?= htmlspecialchars($package) ?></h2>
157 <?php if ($info) : ?>
158 <h3><?= htmlspecialchars($info["title"]) ?><br>
159 <small>License: <?= htmlspecialchars($info["license"]) ?><br>
160 <a href="//pecl.php.net/package/<?= htmlspecialchars($package) ?>">View at PECL</a></small></h3>
161 <?php if (extension_loaded("discount")) : ?>
162 <div class="package-description">
163 <?php
164 $md = MarkdownDocument::createFromString($info["description"]);
165 $md->compile( MarkdownDocument::AUTOLINK |
166 MarkdownDocument::ONE_COMPAT);
167 echo $md->getHtml();
168 ?>
169 </div>
170 <?php else : ?>
171 <p class="package-description">
172 <?= htmlspecialchars($info["description"]) ?>
173 </p>
174 <?php endif; ?>
175 <?php endif; ?>
176 <table class="table table-full versions">
177 <thead>
178 <tr>
179 <th class="text-left" colspan="2">Package</th>
180 <th class="text-left" colspan="<?= count(SIGS) ?>">Signatures</th>
181 <th class="text-left">Date</th>
182 <th class="text-right">Pharext</th>
183 </tr>
184 </thead>
185 <tbody>
186
187 <?php $i = 0; foreach (array_reverse($versions) as $version => $phars) : ++$i; ?>
188 <?php foreach (array_map("array_values", $phars) as $ext => list($phar, $date, $size, $pharext)) : ?>
189 <tr <?php if ($i > NCURRENT) : ?>class="old-version"<?php endif; ?> <?php if ($i === NCURRENT) : ?>id="old"<?php endif; ?>>
190 <?php if (empty($ext)) : ?>
191 <td class="text-left" rowspan="<?= count($phars) ?>">
192 <?= htmlspecialchars($package) ?>
193 <?= htmlspecialchars($version) ?>
194 </td>
195 <?php endif ?>
196
197 <td class="text-left">
198 &#10507;&nbsp;<a href="<?= htmlspecialchars($phar) ?>"
199 download>phar<?= htmlspecialchars($ext) ?></a>&nbsp;<small>(<?= human_size($size) ?>)</small><br>
200 </td>
201 <?php foreach (SIGS as $typ => $sig) : ?>
202 <td>
203 #&nbsp;<a href="<?= sigof($phar, $sig) ?>" download><?= "$typ.$sig" ?></a>
204 </td>
205 <?php endforeach; ?>
206 <td class="text-left">
207 <?= human_date($date); ?>
208
209 </td>
210 <td class="text-right <?= version_compare($pharext, "3.0.1", "<") ? "color-red":"" ?>">
211 v<?= $pharext ?>
212 </td>
213 </tr>
214 <?php endforeach; ?>
215 <?php endforeach; ?>
216
217 </tbody>
218 </table>
219 <?php if ($i >= 3) : ?>
220 <p class="small">
221 <a id="old-toggle" href="#old" onclick="toggleOldVersions(this)">Show
222 <?=count($versions)-NCURRENT?> older version(s) &raquo;</a>
223 <a id="new-toggle" href="#" onclick="toggleOldVersions(this)">Show
224 less versions &laquo;</a>
225 </p>
226 <?php endif; ?>
227
228 <?php else: ?>
229
230 <h2>Available Packages</h2>
231 <form name="search"></form>
232 <ul class="list-inline package-list">
233 <?php foreach (array_map("htmlspecialchars", $packages) as $index => $pkg) : ?>
234 <?php $next = strtolower($pkg[0]); ?>
235 <?php if (isset($prev) && $next != $prev) : ?>
236
237 </ul>
238 <ul class="list-inline package-list">
239 <?php endif; ?>
240
241 <li id="<?= strtolower($pkg) ?>"><a href="?<?= $pkg ?>"><?= $pkg ?></a></li>
242 <?php $prev = $next; ?>
243 <?php endforeach; ?>
244
245 </ul>
246 <?php endif; ?>
247 <hr>
248 <div class="row">
249 <?php if (empty($package)) : ?>
250 <h3>Public keys</h3>
251 <?php else : list($phar) = array_values(current(end($versions))); ?>
252 <h3>Download latest version and signatures:</h3>
253 <div class="column-16">
254 <pre class="code fit-code"><code>
255 curl -sS \
256 -O https://replicator.pharext.org/<?= htmlspecialchars($phar) ?><?php foreach (SIGS as $sig) : ?> \
257 -O https://replicator.pharext.org/<?= htmlspecialchars(sigof($phar, $sig)) ?><?php endforeach; ?></code></pre>
258 </div>
259 </div>
260 <div class="row">
261 <h3>Verify with a public key:</h3>
262 <?php endif; ?>
263
264 <div class="column-8">
265 <h4>RSA <small><a href="replicator.pub" download>replicator.pub</a></small></h4>
266 <?php if (!empty($phar)) : ?>
267 <pre class="code"><code>
268 curl -sSO https://replicator.pharext.org/replicator.pub
269
270 openssl dgst \
271 -verify replicator.pub \
272 -signature <?= htmlspecialchars(basename($phar)).".sig" ?> \
273 <?= htmlspecialchars(basename($phar)) ?></code></pre>
274 <?php endif; ?>
275 <pre class="publickey"><?php readfile("./replicator.pub") ?></pre>
276 </div>
277 <div class="column-8">
278 <h4>OpenPGP <small><a href="4093AEF6.pub" download>4093AEF6.pub</a></small></h4>
279 <?php if (!empty($phar)) : ?>
280 <pre class="code"><code>
281 curl -sSO https://replicator.pharext.org/4093AEF6.pub
282
283 gpg --import 4093AEF6.pub
284
285 gpg --verify <?= htmlspecialchars(basename($phar)).".asc" ?> \
286 <?= htmlspecialchars(basename($phar)) ?></code></pre>
287 <?php endif; ?>
288 <pre class="publickey"><?php readfile("./4093AEF6.pub") ?></pre>
289 </div>
290 </div>
291 </div>
292 <div class="footer">
293 <footer>
294 &copy; 2015 <a href="https://m6w6.name">m6w6</a>, Michael Wallner &mdash; Powered by <a href="//github.com/m6w6/pharext">pharext
295 <?php
296 require_once "../vendor/autoload.php";
297 printf("v%s\n", pharext\Metadata::version());
298 ?>
299 </a>
300 </footer>
301 </div>
302 <script type="text/javascript">
303 function searchPackages(search, regex) {
304 console.log("searchPackages", search, regex);
305 document.querySelectorAll("ul.package-list li").forEach(function(li) {
306 if (regex) {
307 if (li.id.match(search.toLowerCase())) {
308 li.style.removeProperty("display");
309 } else {
310 li.style.display = "none";
311 }
312 } else {
313 if (li.id.startsWith(search.toLowerCase())) {
314 li.style.removeProperty("display");
315 } else {
316 li.style.display = "none";
317 }
318 }
319 });
320 }
321
322 document.body.onload = function() {
323 var form = document.querySelector("form[name=search]");
324
325 if (!form) return;
326
327 var input = document.createElement("input");
328 var reset = document.createElement("input");
329 var prefix_label = document.createElement("label");
330 var prefix = document.createElement("input");
331 var regex_label = document.createElement("label");
332 var regex = document.createElement("input");
333
334 form.onreset = function() {
335 searchPackages("", false);
336 };
337
338 input.id = "s";
339 input.autocomplete = "off";
340 input.name = "s";
341 input.type = "search";
342 input.placeholder = "Search...";
343 input.oninput = function() {
344 searchPackages(input.value, regex.checked);
345 };
346 input.style.paddingRight = "4ch";
347 form.appendChild(input);
348
349 reset.id = "r";
350 reset.name = "r";
351 reset.type = "reset";
352 reset.value = "☒";
353 reset.title = "Reset";
354 reset.style.marginLeft = "-4ch";
355 reset.style.marginRight = "4ch";
356 reset.style.border = "none";
357 reset.style.background = "transparent";
358 form.appendChild(reset);
359
360 prefix.id = "prefix";
361 prefix.name = "by";
362 prefix.value = "prefix";
363 prefix.type = "radio";
364 prefix.defaultChecked = true;
365 prefix.checked = true;
366 prefix.onchange = function() {
367 searchPackages(input.value, regex.checked);
368 };
369 //form.appendChild(prefix);
370 prefix_label.innerText = "by Prefix";
371 prefix_label.appendChild(prefix);
372 form.appendChild(prefix_label);
373
374 regex.id = "regex";
375 regex.name = "by";
376 regex.value = "regex";
377 regex.type = "radio";
378 regex.checked = false;
379 regex.onchange = function() {
380 searchPackages(input.value, regex.checked);
381 };
382 //form.appendChild(regex);
383 regex_label.innerText = "by RegExp";
384 regex_label.appendChild(regex);
385 form.appendChild(regex_label);
386
387 form.after(document.createElement("HR"));
388
389 input.focus();
390 };
391
392 function toggleOldVersions(a) {
393 var nodes, row_style;
394
395 if (a.hash.substring(1) === "old") {
396 row_style = "table-row";
397 document.getElementById("old-toggle").style.display = "none";
398 document.getElementById("new-toggle").style.display = "inline";
399 } else {
400 row_style = "none";
401 document.getElementById("old-toggle").style.display = "inline";
402 document.getElementById("new-toggle").style.display = "none";
403 }
404
405 nodes = document.querySelectorAll("table.versions>tbody>tr.old-version");
406
407 for (var i = 0; i < nodes.length; ++i) {
408 nodes.item(i).style.display = row_style;
409 }
410 }
411 </script>
412 </body>
413 </html>
414 <?php
415 $res->send();
416 ?>