dark mode
[pharext/replicator.pharext.org] / public / html.php
index 8ab447036e0f8b7c0b768ca67fe8f5e44b630ba3..759165e0ff7d68bf29f53a31a4695b0244ec1c27 100644 (file)
@@ -1,9 +1,14 @@
 <?php
 const INCLUDED = __FILE__;
+const NCURRENT = 2;
+
+$css = "concise/css/concise.min.css";
+$fnt = "//fonts.googleapis.com/css?family=Droid+Sans";
 
 require_once "index.php";
 
 ob_start($res);
+$res->addHeader("Link", "<" . dirname((new http\Env\Url)->path) . "/" . $css . ">; rel=preload; as=style");
 
 ?>
 <!doctype html>
@@ -11,9 +16,10 @@ ob_start($res);
        <head>
                <meta charset="utf-8">
                <title>Replicator</title>
-               <link rel="stylesheet" href="concise/css/concise.min.css">
-               <link href="//fonts.googleapis.com/css?family=Droid+Sans" rel="stylesheet" type="text/css">
+               <link rel="stylesheet" href="<?=$css?>">
+               <link rel="stylesheet" href="<?=$fnt?>">
                <meta name="viewport" content="width=device-width, initial-scale=1">
+               <meta name="color-scheme" content="dark light">
                <style>
                        body {
                                padding-bottom: 2em;
@@ -31,12 +37,11 @@ ob_start($res);
                        }
                        .header, .footer {
                                position: fixed;
-                               box-shadow: 0px 0px .8em .4em #89a;
-                               background: #62B3E7;
                                padding: .5em 0;
                        }
                        .header h1 {
                                font-weight: bold;
+                               line-height:120%;
                        }
                        .header h1 a, .footer a:hover {
                                text-decoration: none;
@@ -44,18 +49,12 @@ ob_start($res);
                        .header h1 a:hover {
                                text-decoration: underline;
                        }
-                       .header h1 big {
+                       .header h1 a {
                                /* normalize browser difference */
                                font-size: 1.3em;
                        }
-                       .header h1 big, .footer, .footer a {
-                               color: #fdfdfd;
-                               text-shadow: grey 0 0 .1em;
-                       }
                        .header h1 small {
-                               color: #666;
                                font-size: 1.3rem;
-                               text-shadow: white 0 0 .2em;
                        }
                        li {
                                list-style-type: circle;
@@ -63,22 +62,80 @@ ob_start($res);
                        pre.publickey {
                                font-size: .8rem;
                                line-height: 1rem;
-                               word-wrap: none;
-                       }
-                       code {
-                               background: #EEE;
-                               padding: .1rem;
-                               border-radius: 4px;
                        }
                        pre.code {
                                background: #333;
                                color: #62B3E7;
-                               padding: 1em;
+                               padding: 0 1.5em 1.5em 1em;
                                border-radius: 4px;
                                margin-right: 2em;
+                               display: inline-block;
+                       }
+                       pre.code>code {
+                               font-size: .9rem;
+                       }
+                       .row>h3 {
+                               margin-bottom: 0;
+                       }
+                       hr {
+                               margin: 2em 0;
+                       }
+                       @media(max-width: 80em) {
+                               .column-8 {
+                                       float: none;
+                                       width: auto;
+                               }
+                       }
+                       .old-version, #new-toggle {
+                               display: none;
+                       }
+                       p.package-description, div.package-description p {
+                               white-space: pre-line;
+                       }
+                       .package-list {
+                       }
+                       .package-ch {
+                       }
+                       form * {
+                               display: inline-block;
+                               margin-right: 1em;
                        }
-                       pre.code code {
-                               background: transparent;
+                       form label input{
+                               margin-left: 1em;
+                               vertical-align: middle;
+                       }
+                       form input[type=reset] {
+                               padding: 0;
+                       }
+                       .header, .footer {
+                               box-shadow: 0px 0px .8em .4em #89a;
+                               background: #62B3E7;
+                       }
+                       .header h1 a, .footer, .footer a {
+                               color: #fdfdfd;
+                               text-shadow: grey 0 0 .1em;
+                       }
+                       .header h1 small {
+                               color: #666;
+                               text-shadow: white 0 0 .2em;
+                       }
+                       @media (prefers-color-scheme: dark) {
+                               .header, .footer {
+                                       box-shadow: 0px 0px .8em .4em #123;
+                                       background: #305872;
+                               }
+                               .header h1 a, .footer, .footer a {
+                                       color: #bdbdbd;
+                                       text-shadow: dimgrey 0 0 .1em;
+                               }
+                               .header h1 small {
+                                       color: #aaa;
+                                       text-shadow: black 0 0 .2em;
+                               }
+                               body, h2, h3, h4, h5, h6 {
+                                       background: #3a3b3f;
+                                       color: #bdbdbd;
+                               }
                        }
                </style>
        </head>
@@ -86,7 +143,7 @@ ob_start($res);
                <div class="header">
                        <header>
                                <h1 class="container">
-                                       <a href="?"><big>Replicator</big></a><br>
+                                       <a href="?">Replicator</a><br>
                                        <small>Replicating PECL releases as pharext packages since 2015</small>
                                </h1>
                                <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>
@@ -94,42 +151,58 @@ ob_start($res);
                </div>
                <div class="container">
 
-                       <?php if (!empty($package)) : ?>
+                       <?php if (!empty($package)) : $versions = package_versions($package); $info = package_info($package); ?>
 
                        <h2><?= htmlspecialchars($package) ?></h2>
-                       <table class="table table-full">
+                       <?php if ($info) : ?>
+                               <h3><?= htmlspecialchars($info["title"]) ?><br>
+                                       <small>License: <?= htmlspecialchars($info["license"]) ?><br>
+                                               <a href="//pecl.php.net/package/<?= htmlspecialchars($package) ?>">View at PECL</a></small></h3>
+                               <?php if (extension_loaded("discount")) : ?>
+                               <div class="package-description">
+                                       <?php
+                                       $md = MarkdownDocument::createFromString($info["description"]);
+                                       $md->compile(   MarkdownDocument::AUTOLINK |
+                                                                       MarkdownDocument::ONE_COMPAT);
+                                       echo $md->getHtml();
+                                       ?>
+                               </div>
+                               <?php else : ?>
+                               <p class="package-description">
+                                       <?= htmlspecialchars($info["description"]) ?>
+                               </p>
+                               <?php endif; ?>
+                       <?php endif; ?>
+                       <table class="table table-full versions">
                                <thead>
                                        <tr>
-                                               <th class="text-left" colspan="4">Package</th>
+                                               <th class="text-left" colspan="2">Package</th>
+                                               <th class="text-left" colspan="<?= count(SIGS) ?>">Signatures</th>
                                                <th class="text-left">Date</th>
                                                <th class="text-right">Pharext</th>
                                        </tr>
                                </thead>
                                <tbody>
 
-                                       <?php foreach (array_reverse(package_versions($package)) as $version => $phars) : ?>
-
-                                       <tr>
-                                               <td class="text-left">
+                                       <?php $i = 0; foreach (array_reverse($versions) as $version => $phars) : ++$i; ?>
+                                               <?php foreach (array_map("array_values", $phars) as $ext => list($phar, $date, $size, $pharext)) : ?>
+                                       <tr <?php if ($i > NCURRENT) : ?>class="old-version"<?php endif; ?> <?php if ($i === NCURRENT) : ?>id="old"<?php endif; ?>>
+                                               <?php if (empty($ext)) : ?>
+                                               <td class="text-left" rowspan="<?= count($phars) ?>">
                                                        <?= htmlspecialchars($package) ?>
                                                        <?= htmlspecialchars($version) ?>
                                                </td>
+                                               <?php endif ?>
 
-                                               <?php foreach (array_map("array_values", $phars) as $ext => list($phar, $date, $size, $pharext)) : ?>
                                                <td class="text-left">
                                                        &#10507;&nbsp;<a href="<?= htmlspecialchars($phar) ?>"
-                                                          download>ext.phar<?= htmlspecialchars($ext) ?></a>&nbsp;<small>(<?= human_size($size) ?>)</small><br>
-
+                                                          download>phar<?= htmlspecialchars($ext) ?></a>&nbsp;<small>(<?= human_size($size) ?>)</small><br>
+                                               </td>
                                                        <?php foreach (SIGS as $typ => $sig) : ?>
-                                                               <small>#&nbsp;<a href="<?= sigof($phar, $sig) ?>" download><?= "$typ.$sig" ?></a></small>
-                                                       <?php endforeach; ?>
+                                               <td>
+                                                               #&nbsp;<a href="<?= sigof($phar, $sig) ?>" download><?= "$typ.$sig" ?></a>
                                                </td>
-                                               <?php endforeach; ?>
-                                               <?php for($i = 0; $i < 3-count($phars); ++$i) : ?>
-
-                                               <td></td>
-                                               <?php endfor; ?>
-
+                                                       <?php endforeach; ?>
                                                <td class="text-left">
                                                        <?= human_date($date); ?>
 
@@ -138,84 +211,83 @@ ob_start($res);
                                                        v<?= $pharext ?>
                                                </td>
                                        </tr>
+                                               <?php endforeach; ?>
                                        <?php endforeach; ?>
 
                                </tbody>
                        </table>
+                               <?php if ($i >= 3) : ?>
+                                       <p class="small">
+                                               <a id="old-toggle" href="#old" onclick="toggleOldVersions(this)">Show
+                                                       <?=count($versions)-NCURRENT?> older version(s) &raquo;</a>
+                                               <a id="new-toggle" href="#" onclick="toggleOldVersions(this)">Show
+                                                       less versions &laquo;</a>
+                                       </p>
+                               <?php endif; ?>
+
                        <?php else:     ?>
 
                        <h2>Available Packages</h2>
-                       <ul class="list-inline">
-                       <?php foreach (array_map("htmlspecialchars", $packages) as $index => $package) : ?>
-                               <?php $next = strtolower($package{0}); ?>
+                       <form name="search"></form>
+                       <ul class="list-inline package-list">
+                       <?php foreach (array_map("htmlspecialchars", $packages) as $index => $pkg) : ?>
+                               <?php $next = strtolower($pkg[0]); ?>
                                <?php if (isset($prev) && $next != $prev) : ?>
 
                        </ul>
-                       <ul class="list-inline">
+                       <ul class="list-inline package-list">
                                <?php endif; ?>
 
-                               <li><a href="?<?= $package ?>"><?=  $package ?></a></li>
+                               <li id="<?= strtolower($pkg) ?>"><a href="?<?= $pkg ?>"><?=  $pkg ?></a></li>
                                <?php $prev = $next; ?>
                        <?php endforeach; ?>
 
                        </ul>
                        <?php endif; ?>
-               </div>
-               <div class="container">
-                       <h3>Public Keys</h3>
-                       <div class="column-8">
-                               <h4>RSA <small><a href="replicator.pub" download>replicator.pub</a></small></h4>
-                               <p>Verify with:</p>
-                                       <pre class="code"><code># openssl dgst \
-       -verify replicator.pub \
-       -signature <?= isset($phar) ? htmlspecialchars(basename($phar)).".sig" : "apfd-1.0.1.ext.phar.sig" ?> \
-                  <?= isset($phar) ? htmlspecialchars(basename($phar)): "apfd-1.0.1.ext.phar" ?></code></pre>
-                               <pre class="publickey">
------BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzsDXNox5V0V9GLcnXEu
-kxnhFs9+/AMm//1qJAoNwP6sgmYShuyI3NDZzCmT7tOIcpqW0I4P8D1Psrftyqbt
-spedAvyOLCLZXaOuE130aMlvfqEiO+s8ZVZL8aHLE/orLbpOexEs33a1j6shl5C6
-MoojzK3uYccL4XJfj0t2nrC+XMfWE9oQGvyLZv3tNCzH4Oy7knWVVy10EKbKgPft
-izCFR+0mPYw35RN3gAGrug+khnVRMRNpS7B0uZ6E29Bgsrud9l91mVbrL+DaoaSa
-IFGeYuFGe2ZpHUfxf16S0w7ybPrrJJsD6cYOtwXjRZo+4ux6PdKZ+m3hnKWoj9IF
-OwIDAQAB
------END PUBLIC KEY-----</pre>
+                       <hr>
+                       <div class="row">
+               <?php if (empty($package)) : ?>
+                               <h3>Public keys</h3>
+               <?php else : list($phar) = array_values(current(end($versions))); ?>
+                               <h3>Download latest version and signatures:</h3>
+                               <div class="column-16">
+                                       <pre class="code fit-code"><code>
+curl -sS \
+     -O https://replicator.pharext.org/<?= htmlspecialchars($phar) ?><?php foreach (SIGS as $sig) : ?> \
+     -O https://replicator.pharext.org/<?= htmlspecialchars(sigof($phar, $sig)) ?><?php endforeach; ?></code></pre>
+                               </div>
                        </div>
-                       <div class="column-8">
-                               <h4>OpenPGP <small><a href="4093AEF6.pub" download>4093AEF6.pub</a></small></h4>
-                               <p>Verify with:</p>
-                                       <pre class="code"><code># gpg --import 4093AEF6.pub
+                       <div class="row">
+                               <h3>Verify with a public key:</h3>
+               <?php endif; ?>
 
-# gpg --verify <?= isset($phar) ? htmlspecialchars(basename($phar)).".asc" : "apfd-1.0.1.ext.phar.asc" ?> \
-               <?= isset($phar) ? htmlspecialchars(basename($phar)): "apfd-1.0.1.ext.phar" ?></code></pre>
-                               </p>
-                               <pre class="publickey">
------BEGIN PGP PUBLIC KEY BLOCK-----
-
-mQENBFcBXgsBCACfOwNc2jHlXRX0YtydcS6TGeEWz378Ayb//WokCg3A/qyCZhKG
-7Ijc0NnMKZPu04hympbQjg/wPU+yt+3Kpu2yl50C/I4sItldo64TXfRoyW9+oSI7
-6zxlVkvxocsT+istuk57ESzfdrWPqyGXkLoyiiPMre5hxwvhcl+PS3aesL5cx9YT
-2hAa/Itm/e00LMfg7LuSdZVXLXQQpsqA9+2LMIVH7SY9jDflE3eAAau6D6SGdVEx
-E2lLsHS5noTb0GCyu532X3WZVusv4NqhpJogUZ5i4UZ7ZmkdR/F/XpLTDvJs+usk
-mwPpxg63BeNFmj7i7Ho90pn6beGcpaiP0gU7ABEBAAG0K1BIQVJleHQgUmVwbGlj
-YXRvciA8cmVwbGljYXRvckBwaGFyZXh0Lm9yZz6JATcEEwEKACEFAlcBXgsCGwMF
-CwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQZJhrlUCTrvbYGAgAi120YHruidld
-uPTUS05/ZLoSn3orKkmkskOsjBrUqJvQHx1s8mqJpNJdbIrgPIxQPHauiE6Fj72q
-uv6TsVRxM+7VjiCHTbHmDheP5Zcyac7Nd/e62DsCYP7LAAx7MHbQvki6XQg4EsQZ
-cXMKRYuuizJxNGVUeZpusY5WXmc5PRIigsI4eh/2l96IK/eqTDSZiDUwv9ze+HMf
-JxOunBZVebYUQ3RYEWx1NseInxbiAnEdGM7phZH43jkohxPLROr3nWBmrJbBqULn
-m6M5fRucJoldU8VIzMdy0xxu+3PuX8aug96njK448r53wjb7yRf6WLonwjlFqTWq
-0tZzZR3Nd4kBHAQTAQoABgUCVwFehAAKCRBIDj4UsKTHx8iNB/0dl+8T8zp0Pksc
-jGo8WBA8sfdnMqaE/NkUCbMhT5wkAk+4JRlv/DUfokB6cF87yQCC/IjVAapPT2xS
-h31QubsjfnfrqSiF4ls8JCTLp/xkafx+tFsJKJOEgCsoeFCOeZBfvhhLPwLyhHLZ
-ZIsHmYX8YEeku+gsbQIVnWC06WJbJ5HuKByr8VEpgGBig4eRRMcDTJShgDQhn476
-VLKah3xplnU6bgOzsLn1Ssv095DOouh7tZabkS4jtvDAQK/1g2VQ/d0sOrbKAugQ
-IHEcyAQedGERU0JqXrXW9WdOqs1AZTl/YGWe94kZqJ1XSWibTSq1TUNCtTcrW558
-yImBVgJx
-=nFzc
------END PGP PUBLIC KEY BLOCK-----</pre>
+                               <div class="column-8">
+                                       <h4>RSA <small><a href="replicator.pub" download>replicator.pub</a></small></h4>
+                                       <?php if (!empty($phar)) : ?>
+                                       <pre class="code"><code>
+curl -sSO https://replicator.pharext.org/replicator.pub
+
+openssl dgst \
+       -verify replicator.pub \
+       -signature <?= htmlspecialchars(basename($phar)).".sig" ?> \
+                  <?= htmlspecialchars(basename($phar)) ?></code></pre>
+                                       <?php endif; ?>
+                                       <pre class="publickey"><?php readfile("./replicator.pub") ?></pre>
+                               </div>
+                               <div class="column-8">
+                                       <h4>OpenPGP <small><a href="4093AEF6.pub" download>4093AEF6.pub</a></small></h4>
+                                       <?php if (!empty($phar)) : ?>
+                                       <pre class="code"><code>
+curl -sSO https://replicator.pharext.org/4093AEF6.pub
+
+gpg --import 4093AEF6.pub
+
+gpg --verify <?= htmlspecialchars(basename($phar)).".asc" ?> \
+             <?= htmlspecialchars(basename($phar)) ?></code></pre>
+                                       <?php endif; ?>
+                               <pre class="publickey"><?php readfile("./4093AEF6.pub") ?></pre>
+                               </div>
                        </div>
-                       <div style="clear:both"></div>
                </div>
                <div class="footer">
                        <footer>
@@ -227,6 +299,116 @@ yImBVgJx
                                </a>
                        </footer>
                </div>
+               <script type="text/javascript">
+               function searchPackages(search, regex) {
+                       console.log("searchPackages", search, regex);
+                       document.querySelectorAll("ul.package-list li").forEach(function(li) {
+                               if (regex) {
+                                       if (li.id.match(search.toLowerCase())) {
+                                               li.style.removeProperty("display");
+                                       } else {
+                                               li.style.display = "none";
+                                       }
+                               } else {
+                                       if (li.id.startsWith(search.toLowerCase())) {
+                                               li.style.removeProperty("display");
+                                       } else {
+                                               li.style.display = "none";
+                                       }
+                               }
+                       });
+               }
+
+               document.body.onload = function() {
+                       var form = document.querySelector("form[name=search]");
+
+                       if (!form) return;
+
+                       var input = document.createElement("input");
+                       var reset = document.createElement("input");
+                       var prefix_label = document.createElement("label");
+                       var prefix = document.createElement("input");
+                       var regex_label = document.createElement("label");
+                       var regex = document.createElement("input");
+
+                       form.onreset = function() {
+                               searchPackages("", false);
+                       };
+
+                       input.id = "s";
+                       input.autocomplete = "off";
+                       input.name = "s";
+                       input.type = "search";
+                       input.placeholder = "Search...";
+                       input.oninput = function() {
+                               searchPackages(input.value, regex.checked);
+                       };
+                       input.style.paddingRight = "4ch";
+                       form.appendChild(input);
+
+                       reset.id = "r";
+                       reset.name = "r";
+                       reset.type = "reset";
+                       reset.value = "☒";
+                       reset.title = "Reset";
+                       reset.style.marginLeft = "-4ch";
+                       reset.style.marginRight = "4ch";
+                       reset.style.border = "none";
+                       reset.style.background = "transparent";
+                       form.appendChild(reset);
+
+                       prefix.id = "prefix";
+                       prefix.name = "by";
+                       prefix.value = "prefix";
+                       prefix.type = "radio";
+                       prefix.defaultChecked = true;
+                       prefix.checked = true;
+                       prefix.onchange = function() {
+                               searchPackages(input.value, regex.checked);
+                       };
+                       //form.appendChild(prefix);
+                       prefix_label.innerText = "by Prefix";
+                       prefix_label.appendChild(prefix);
+                       form.appendChild(prefix_label);
+
+                       regex.id = "regex";
+                       regex.name = "by";
+                       regex.value = "regex";
+                       regex.type = "radio";
+                       regex.checked = false;
+                       regex.onchange = function() {
+                               searchPackages(input.value, regex.checked);
+                       };
+                       //form.appendChild(regex);
+                       regex_label.innerText = "by RegExp";
+                       regex_label.appendChild(regex);
+                       form.appendChild(regex_label);
+
+                       form.after(document.createElement("HR"));
+
+                       input.focus();
+               };
+
+               function toggleOldVersions(a) {
+                       var nodes, row_style;
+
+                       if (a.hash.substring(1) === "old") {
+                               row_style = "table-row";
+                               document.getElementById("old-toggle").style.display = "none";
+                               document.getElementById("new-toggle").style.display = "inline";
+                       } else {
+                               row_style = "none";
+                               document.getElementById("old-toggle").style.display = "inline";
+                               document.getElementById("new-toggle").style.display = "none";
+                       }
+
+                       nodes = document.querySelectorAll("table.versions>tbody>tr.old-version");
+
+                       for (var i = 0; i < nodes.length; ++i) {
+                               nodes.item(i).style.display = row_style;
+                       }
+               }
+               </script>
        </body>
 </html>
 <?php