Author: Derick Rethans (derickr)
Date: 2025-08-12T14:29:37+01:00

Commit: 
https://github.com/php/web-php/commit/ccdc6ca8bb5417a12815c78e659fbefcce7e5aec
Raw diff: 
https://github.com/php/web-php/commit/ccdc6ca8bb5417a12815c78e659fbefcce7e5aec.diff

Merged pull request #1287

Changed paths:
  A  downloads-get-instructions.php
  A  include/download-instructions/fw-drupal.php
  A  include/download-instructions/fw-laravel.php
  A  include/download-instructions/fw-symfony.php
  A  include/download-instructions/fw-wordpress.php
  A  include/download-instructions/linux-debian-cli-community.php
  A  include/download-instructions/linux-debian-cli-default.php
  A  include/download-instructions/linux-debian-web-community.php
  A  include/download-instructions/linux-debian-web-default.php
  A  include/download-instructions/linux-fedora-cli-community.php
  A  include/download-instructions/linux-fedora-cli-default.php
  A  include/download-instructions/linux-fedora-web-community.php
  A  include/download-instructions/linux-fedora-web-default.php
  A  include/download-instructions/linux-redhat-cli-community.php
  A  include/download-instructions/linux-redhat-cli-default.php
  A  include/download-instructions/linux-redhat-web-community.php
  A  include/download-instructions/linux-redhat-web-default.php
  A  include/download-instructions/linux-source.php
  A  include/download-instructions/linux-ubuntu-cli-community.php
  A  include/download-instructions/linux-ubuntu-cli-default.php
  A  include/download-instructions/linux-ubuntu-web-community.php
  A  include/download-instructions/linux-ubuntu-web-default.php
  A  include/download-instructions/osx-homebrew-php.php
  A  include/download-instructions/osx-homebrew.php
  A  include/download-instructions/osx-macports.php
  A  include/download-instructions/osx-source.php
  A  include/download-instructions/windows-chocolatey.php
  A  include/download-instructions/windows-native.php
  A  include/download-instructions/windows-scoop.php
  A  include/download-instructions/windows-source.php
  A  include/download-instructions/windows.ps1
  A  js/ext/prism.js
  A  styles/code-syntax.css
  A  styles/prism.css
  M  downloads.php
  M  include/header.inc
  M  include/version.inc
  M  styles/theme-base.css


Diff:

diff --git a/downloads-get-instructions.php b/downloads-get-instructions.php
new file mode 100644
index 0000000000..aabc617978
--- /dev/null
+++ b/downloads-get-instructions.php
@@ -0,0 +1,83 @@
+<?php
+$file = 'unknown';
+$latestPhpVersion = '8.4';
+
+if (!isset($options)) {
+    $options = [
+        'os' => '',
+        'usage' => '',
+        'version' => '',
+    ];
+}
+
+if ($options['os'] === 'windows') {
+    if ($options['osvariant'] === 'windows-wsl-debian') {
+        $options['os'] = 'linux';
+        $options['osvariant'] = 'linux-debian';
+    }
+    if ($options['osvariant'] === 'windows-wsl-ubuntu') {
+        $options['os'] = 'linux';
+        $options['osvariant'] = 'linux-ubuntu';
+    }
+}
+if ($options['os'] === 'osx' || $options['os'] === 'windows') {
+    if ($options['version'] === 'default') {
+        $options['version'] = $latestPhpVersion;
+    }
+}
+
+if (in_array($options['usage'], ['fw-drupal', 'fw-laravel', 'fw-symfony', 
'fw-wordpress'])) {
+    $file = "{$options['usage']}";
+    $options['os'] = null;
+}
+
+$multiversion = false;
+
+if (array_key_exists('multiversion', $options)) {
+    $multiversion = $options['multiversion'] === 'Y';
+}
+
+$source = false;
+
+if (array_key_exists('source', $options)) {
+    if ($options['source'] === 'Y') {
+        $source = $options['source'] === 'Y';
+    }
+}
+
+switch ($options['os']) {
+    case 'linux':
+        $defaultOrCommunity = ($options['version'] !== 'default' || 
$multiversion) ? 'community' : 'default';
+        if ($defaultOrCommunity === 'community' && $options['version'] == 
'default') {
+            $options['version'] = $latestPhpVersion;
+        }
+        $file = 
"{$options['osvariant']}-{$options['usage']}-{$defaultOrCommunity}";
+        break;
+    case 'osx':
+    case 'windows':
+        $file = "{$options['osvariant']}";
+        break;
+}
+
+if ($source) {
+    $file = "{$options['os']}-source";
+}
+
+$version = $options['version'];
+$versionNoDot = str_replace('.', '', $version);
+
+if (file_exists(__DIR__ . "/include/download-instructions/{$file}.php")) {
+    include __DIR__ . "/include/download-instructions/{$file}.php";
+    if ($source) {
+        return false;
+    }
+    return true;
+} else {
+?>
+<p>
+    There are no instructions yet. Try using the <a 
href="https://www.php.net/manual/en/install.php";>generic installation from 
source</a>.
+</p>
+<?php
+    return false;
+}
+?>
diff --git a/downloads.php b/downloads.php
index 5468da840f..ae8ba587d4 100644
--- a/downloads.php
+++ b/downloads.php
@@ -7,8 +7,6 @@
 // Try to make this page non-cached
 header_nocache();
 
-$SHOW_COUNT = 4;
-
 $SIDEBAR_DATA = '
 <div class="panel">
   <a href="/supported-versions.php">Supported Versions</a>
@@ -18,6 +16,7 @@
   </div>
 </div>
 
+<p class="panel"><a href="downloads.php?source=Y">Source Tarballs</a></p>
 <p class="panel"><a href="download-docs.php">Documentation Download</a></p>
 <p class="panel"><a href="download-logos.php">PHP Logos</a></p>
 
@@ -37,14 +36,164 @@
             ],
         ],
         "current" => "downloads",
+        "css" => [
+            "prism.css",
+            "code-syntax.css",
+        ],
+        "js_files" => [
+            "js/ext/prism.js",
+        ],
     ],
 );
+
+function option(string $value, string $desc, $attributes = []): string
+{
+    return '<option value="' . $value . '"' . implode(' ', 
array_keys(array_filter($attributes))) . '>' . $desc . '</option>';
+}
+
+$usage = [
+    'web' => 'Web Development',
+    'cli' => 'CLI/Library Development',
+    'fw-drupal' => 'Drupal Development',
+    'fw-laravel' => 'Laravel Development',
+    'fw-symfony' => 'Symfony Development',
+    'fw-wordpress' => 'WordPress Development',
+];
+
+$os = [
+    'linux' => [
+        'name' => 'Linux',
+        'variants' => [
+            'linux-debian' => 'Debian',
+            'linux-fedora' => 'Fedora',
+            'linux-redhat' => 'RedHat',
+            'linux-ubuntu' => 'Ubuntu',
+        ],
+    ],
+    'osx' => [
+        'name' => 'macOS',
+        'variants' => [
+            'osx-homebrew' => 'Homebrew/Brew',
+            'osx-homebrew-php' => 'Homebrew/Homebrew-PHP',
+            'osx-macports' => 'MacPorts',
+        ],
+    ],
+    'windows' => [
+        'name' => 'Windows',
+        'variants' => [
+            'windows-native' => 'Windows Native Build',
+            'windows-chocolatey' => 'Windows with Chocolatey',
+            'windows-scoop' => 'Windows with Scoop',
+            'windows-wsl-debian' => 'Windows with WSL/Debian',
+            'windows-wsl-ubuntu' => 'Windows with WSL/Ubuntu',
+        ],
+    ],
+];
+
+$versions = [
+    '8.4' => 'version 8.4',
+    '8.3' => 'version 8.3',
+    '8.2' => 'version 8.2',
+    '8.1' => 'version 8.1',
+    'default' => 'OS default version',
+];
+
+$defaults = [
+    'os' => 'linux',
+    'version' => 'default',
+    'usage' => 'web',
+];
+
+$options = array_merge($defaults, $_GET);
+if (!array_key_exists('osvariant', $options) || 
!array_key_exists($options['osvariant'], $os[$options['os']]['variants'])) {
+    $options['osvariant'] = array_key_first($os[$options['os']]['variants']);
+}
 ?>
 <h1>Downloads &amp; Installation Instructions</h1>
 
+    <form class="instructions-form" id="instructions-form">
+    <div class="instructions-row">
+        I want to use PHP for
+        <select id="usage" name="usage">
+            <?php foreach ($usage as $value => $description) { ?>
+                <?= option($value, $description, [
+                    'selected' => array_key_exists('usage', $options) && 
$options['usage'] === $value,
+                ]); ?>
+            <?php } ?>
+        </select>.
+    </div>
+
+    <div class="instructions-row">
+        I work with
+        <select id="os" name="os">
+            <?php foreach ($os as $value => $item) { ?>
+                <?= option($value, $item['name'], [
+                    'selected' => array_key_exists('os', $options) && 
$options['os'] === $value,
+                ]); ?>
+            <?php } ?>
+        </select>
+
+        <?php if (array_key_exists('os', $options) && 
array_key_exists('osvariant', $options)) { ?>
+            <select id="osvariant" name="osvariant">
+                <?php foreach ($os[$options['os']]['variants'] as $value => 
$description) { ?>
+                    <?= option($value, $description, [
+                        'selected' => $options['osvariant'] === $value,
+                    ]); ?>
+                <?php } ?>
+            </select>
+        <?php } ?>,
+        and use
+        <select id="version" name="version">
+            <?php foreach ($versions as $value => $version) { ?>
+                <?= option($value, $version, [
+                    'selected' => array_key_exists('version', $options) && 
$options['version'] === $value,
+                ]); ?>
+            <?php } ?>
+        </select>
+    </div>
+
+    <label for="multiversion" class="instructions-label">
+        I want to be able to use multiple PHP versions:
+        <input type="checkbox" id="multiversion" name="multiversion" value="Y"
+            <?= array_key_exists('multiversion', $options) && 
$options['multiversion'] === 'Y' ? 'checked' : '' ?>/>
+    </label>
+
+    <label for="source" class="instructions-label">
+        I want to compile everything from source:
+        <input type="checkbox" id="source" name="source" value="Y"
+            <?= array_key_exists('source', $options) && $options['source'] === 
'Y' ? 'checked' : '' ?>/>
+    </label>
+
+    <noscript>
+        <button type="submit" class="button">Update Instructions</button>
+    </noscript>
+</form>
+
+<h2>Instructions</h2>
+<div id="instructions" class="instructions">
+<?php $instructionsShown = include 'downloads-get-instructions.php'; ?>
+</div>
+
+<?php if (!$instructionsShown): ?>
+
+<h2>Source Code</h2>
+<?php show_source_releases(); ?>
+
+<hr>
+<h2>GPG Keys</h2>
 <p>
-    <a href="/manual/install.general.php">Installing PHP</a> is covered
-    thoroughly in the PHP documentation.
+The releases are tagged and signed in the <a href='git.php'>PHP Git 
Repository</a>.
+The following official GnuPG keys of the current PHP Release Manager can be 
used
+to verify the tags:
+</p>
+
+<?php gpg_key_show_keys(true /* activeOnly */); ?>
+
+<p>
+  <a href="gpg-keys.php">
+    A full list of GPG keys used for current and older releases is also
+    available.
+  </a>
 </p>
 
 <h2>Binaries</h2>
@@ -65,67 +214,17 @@
     </ul>
 </p>
 
-<h2>Source Code</h2>
-<?php $i = 0; foreach ($RELEASES as $MAJOR => $major_releases): /* major 
releases loop start */
-        $releases = array_slice($major_releases, 0, $SHOW_COUNT);
-?>
-<a id="v<?php echo $MAJOR; ?>"></a>
-<?php foreach ($releases as $v => $a): ?>
-  <?php $mver = substr($v, 0, strrpos($v, '.')); ?>
-  <?php $stable = $i++ === 0 ? "Current Stable" : "Old Stable"; ?>
-
-  <h3 id="v<?php echo $v; ?>" class="title">
-    <span class="release-state"><?php echo $stable; ?></span>
-    PHP <?php echo $v; ?>
-    (<a href="/ChangeLog-<?php echo $MAJOR; ?>.php#<?php echo urlencode($v); 
?>" class="changelog">Changelog</a>)
-  </h3>
-  <div class="content-box">
-
-    <ul>
-      <?php foreach ($a['source'] as $rel): ?>
-        <li>
-          <?php download_link($rel['filename'], $rel['filename']); ?>
-          <span class="releasedate"><?php echo date('d M Y', 
strtotime($rel['date'])); ?></span>
-          <?php
-            if (isset($rel['md5']))    echo '<span class="md5sum">', 
$rel['md5'], '</span>';
-            if (isset($rel['sha256'])) echo '<span class="sha256">', 
$rel['sha256'], '</span>';
-           ?>
-          <?php if (isset($rel['note']) && $rel['note']): ?>
-            <p>
-              <strong>Note:</strong>
-              <?php echo $rel['note']; ?>
-            </p>
-          <?php endif; ?>
-        </li>
-      <?php endforeach; ?>
-      <li>
-        <a href="https://windows.php.net/download#php-<?php echo 
urlencode($mver); ?>">
-          Windows downloads
-        </a>
-      </li>
-    </ul>
-
-    <a href="#gpg-<?php echo $mver; ?>">GPG Keys for PHP <?php echo $mver; 
?></a>
-  </div>
-<?php endforeach; ?>
-<?php endforeach; /* major releases loop end */ ?>
-
-<hr>
-<h2>GPG Keys</h2>
-<p>
-The releases are tagged and signed in the <a href='git.php'>PHP Git 
Repository</a>.
-The following official GnuPG keys of the current PHP Release Manager can be 
used
-to verify the tags:
-</p>
+<?php endif; ?>
 
-<?php gpg_key_show_keys(true /* activeOnly */); ?>
+    <script>
+        window.onload = function () {
+            let form = document.getElementById("instructions-form")
 
-<p>
-  <a href="gpg-keys.php">
-    A full list of GPG keys used for current and older releases is also
-    available.
-  </a>
-</p>
+            form.addEventListener('change', function () {
+                form.submit();
+            });
+        }
+    </script>
 
 <?php
 site_footer(['sidebar' => $SIDEBAR_DATA]);
diff --git a/include/download-instructions/fw-drupal.php 
b/include/download-instructions/fw-drupal.php
new file mode 100644
index 0000000000..20ff7332ae
--- /dev/null
+++ b/include/download-instructions/fw-drupal.php
@@ -0,0 +1,6 @@
+<p>
+Instructions for installing PHP for Drupal development can be found on:
+</p>
+<p>
+» <a 
href='https://www.drupal.org/docs/getting-started/installing-drupal'>https://www.drupal.org/docs/getting-started/installing-drupal</a>
+</p>
diff --git a/include/download-instructions/fw-laravel.php 
b/include/download-instructions/fw-laravel.php
new file mode 100644
index 0000000000..62c4282b6a
--- /dev/null
+++ b/include/download-instructions/fw-laravel.php
@@ -0,0 +1,6 @@
+<p>
+Instructions for installing PHP for Laravel development can be found on:
+</p>
+<p>
+» <a 
href='https://laravel.com/docs/12.x/installation#installing-php'>https://laravel.com/docs/12.x/installation#installing-php</a>
+</p>
diff --git a/include/download-instructions/fw-symfony.php 
b/include/download-instructions/fw-symfony.php
new file mode 100644
index 0000000000..f03259972f
--- /dev/null
+++ b/include/download-instructions/fw-symfony.php
@@ -0,0 +1,6 @@
+<p>
+Instructions for installing PHP for Symfony development can be found on:
+</p>
+<p>
+» <a 
href='https://symfony.com/doc/current/setup.html'>https://symfony.com/doc/current/setup.html</a>
+</p>
diff --git a/include/download-instructions/fw-wordpress.php 
b/include/download-instructions/fw-wordpress.php
new file mode 100644
index 0000000000..1fd289f75d
--- /dev/null
+++ b/include/download-instructions/fw-wordpress.php
@@ -0,0 +1,6 @@
+<p>
+Instructions for installing PHP for WordPress development can be found on:
+</p>
+<p>
+» <a 
href='https://wordpress.org/support/article/how-to-install-wordpress/'>https://wordpress.org/support/article/how-to-install-wordpress/</a>
+</p>
diff --git a/include/download-instructions/linux-debian-cli-community.php 
b/include/download-instructions/linux-debian-cli-community.php
new file mode 100644
index 0000000000..cc1595689a
--- /dev/null
+++ b/include/download-instructions/linux-debian-cli-community.php
@@ -0,0 +1,15 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Add the packages.sury.org/php repository.
+sudo apt-get update
+sudo apt-get install -y lsb-release ca-certificates apt-transport-https curl
+sudo curl -sSLo /tmp/debsuryorg-archive-keyring.deb 
https://packages.sury.org/debsuryorg-archive-keyring.deb
+sudo dpkg -i /tmp/debsuryorg-archive-keyring.deb
+sudo sh -c 'echo "deb 
[signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] 
https://packages.sury.org/php/ $(lsb_release -sc) main" > 
/etc/apt/sources.list.d/php.list'
+sudo apt-get update
+
+# Install PHP.
+sudo apt-get install -y php<?= $version; ?>
+</code></pre>
diff --git a/include/download-instructions/linux-debian-cli-default.php 
b/include/download-instructions/linux-debian-cli-default.php
new file mode 100644
index 0000000000..534da00616
--- /dev/null
+++ b/include/download-instructions/linux-debian-cli-default.php
@@ -0,0 +1,10 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Update the package lists.
+sudo apt update
+
+# Install PHP.
+sudo apt install -y php
+</code></pre>
diff --git a/include/download-instructions/linux-debian-web-community.php 
b/include/download-instructions/linux-debian-web-community.php
new file mode 120000
index 0000000000..b21d40f00c
--- /dev/null
+++ b/include/download-instructions/linux-debian-web-community.php
@@ -0,0 +1 @@
+linux-debian-cli-community.php
\ No newline at end of file
diff --git a/include/download-instructions/linux-debian-web-default.php 
b/include/download-instructions/linux-debian-web-default.php
new file mode 120000
index 0000000000..0017979f66
--- /dev/null
+++ b/include/download-instructions/linux-debian-web-default.php
@@ -0,0 +1 @@
+linux-debian-cli-default.php
\ No newline at end of file
diff --git a/include/download-instructions/linux-fedora-cli-community.php 
b/include/download-instructions/linux-fedora-cli-community.php
new file mode 100644
index 0000000000..3f414122c5
--- /dev/null
+++ b/include/download-instructions/linux-fedora-cli-community.php
@@ -0,0 +1,13 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Add the Remi's RPM repository.
+sudo dnf install -y dnf-plugins-core
+sudo dnf install -y https://rpms.remirepo.net/fedora/remi-release-$(rpm -E 
%fedora).rpm
+sudo dnf module reset php -y
+sudo dnf module enable php:remi-<?= $version; ?> -y
+
+# Install PHP.
+sudo dnf install -y php
+</code></pre>
diff --git a/include/download-instructions/linux-fedora-cli-default.php 
b/include/download-instructions/linux-fedora-cli-default.php
new file mode 100644
index 0000000000..61d64d3c50
--- /dev/null
+++ b/include/download-instructions/linux-fedora-cli-default.php
@@ -0,0 +1,7 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Install PHP.
+sudo dnf install -y php
+</code></pre>
diff --git a/include/download-instructions/linux-fedora-web-community.php 
b/include/download-instructions/linux-fedora-web-community.php
new file mode 120000
index 0000000000..96f87a049c
--- /dev/null
+++ b/include/download-instructions/linux-fedora-web-community.php
@@ -0,0 +1 @@
+linux-fedora-cli-community.php
\ No newline at end of file
diff --git a/include/download-instructions/linux-fedora-web-default.php 
b/include/download-instructions/linux-fedora-web-default.php
new file mode 120000
index 0000000000..83c945fbe5
--- /dev/null
+++ b/include/download-instructions/linux-fedora-web-default.php
@@ -0,0 +1 @@
+linux-fedora-cli-default.php
\ No newline at end of file
diff --git a/include/download-instructions/linux-redhat-cli-community.php 
b/include/download-instructions/linux-redhat-cli-community.php
new file mode 100644
index 0000000000..7a647a04ef
--- /dev/null
+++ b/include/download-instructions/linux-redhat-cli-community.php
@@ -0,0 +1,15 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Add the Remi's RPM repository.
+sudo subscription-manager repos --enable codeready-builder-for-rhel-$(rpm -E 
%rhel)-$(arch)-rpms
+sudo dnf install -y dnf-plugins-core
+sudo dnf install -y 
https://dl.fedoraproject.org/pub/epel/epel-release-latest-$(rpm -E 
%rhel).noarch.rpm
+sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-$(rpm -E 
%rhel).rpm
+sudo dnf module reset php -y
+sudo dnf module enable php:remi-<?= $version; ?> -y
+
+# Install PHP.
+sudo dnf install -y php
+</code></pre>
diff --git a/include/download-instructions/linux-redhat-cli-default.php 
b/include/download-instructions/linux-redhat-cli-default.php
new file mode 100644
index 0000000000..61d64d3c50
--- /dev/null
+++ b/include/download-instructions/linux-redhat-cli-default.php
@@ -0,0 +1,7 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Install PHP.
+sudo dnf install -y php
+</code></pre>
diff --git a/include/download-instructions/linux-redhat-web-community.php 
b/include/download-instructions/linux-redhat-web-community.php
new file mode 120000
index 0000000000..b41bc5d464
--- /dev/null
+++ b/include/download-instructions/linux-redhat-web-community.php
@@ -0,0 +1 @@
+linux-redhat-cli-community.php
\ No newline at end of file
diff --git a/include/download-instructions/linux-redhat-web-default.php 
b/include/download-instructions/linux-redhat-web-default.php
new file mode 120000
index 0000000000..38d6e97f7b
--- /dev/null
+++ b/include/download-instructions/linux-redhat-web-default.php
@@ -0,0 +1 @@
+linux-redhat-cli-default.php
\ No newline at end of file
diff --git a/include/download-instructions/linux-source.php 
b/include/download-instructions/linux-source.php
new file mode 100644
index 0000000000..47437b2c77
--- /dev/null
+++ b/include/download-instructions/linux-source.php
@@ -0,0 +1,4 @@
+<p>
+       The <a 
href="https://www.php.net/manual/en/install.unix.source.php";>instructions for 
compiling from source
+       on Linux</a> are described in the PHP manual.
+</p>
diff --git a/include/download-instructions/linux-ubuntu-cli-community.php 
b/include/download-instructions/linux-ubuntu-cli-community.php
new file mode 100644
index 0000000000..100666c8ea
--- /dev/null
+++ b/include/download-instructions/linux-ubuntu-cli-community.php
@@ -0,0 +1,13 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Add the ondrej/php repository.
+sudo apt update
+sudo apt install -y software-properties-common
+sudo LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php -y
+sudo apt update
+
+# Install PHP.
+sudo apt install -y php<?= $version; ?>
+</code></pre>
diff --git a/include/download-instructions/linux-ubuntu-cli-default.php 
b/include/download-instructions/linux-ubuntu-cli-default.php
new file mode 100644
index 0000000000..534da00616
--- /dev/null
+++ b/include/download-instructions/linux-ubuntu-cli-default.php
@@ -0,0 +1,10 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Update the package lists.
+sudo apt update
+
+# Install PHP.
+sudo apt install -y php
+</code></pre>
diff --git a/include/download-instructions/linux-ubuntu-web-community.php 
b/include/download-instructions/linux-ubuntu-web-community.php
new file mode 120000
index 0000000000..cbcc4a6ff3
--- /dev/null
+++ b/include/download-instructions/linux-ubuntu-web-community.php
@@ -0,0 +1 @@
+linux-ubuntu-cli-community.php
\ No newline at end of file
diff --git a/include/download-instructions/linux-ubuntu-web-default.php 
b/include/download-instructions/linux-ubuntu-web-default.php
new file mode 120000
index 0000000000..c4a0004521
--- /dev/null
+++ b/include/download-instructions/linux-ubuntu-web-default.php
@@ -0,0 +1 @@
+linux-ubuntu-cli-default.php
\ No newline at end of file
diff --git a/include/download-instructions/osx-homebrew-php.php 
b/include/download-instructions/osx-homebrew-php.php
new file mode 100644
index 0000000000..5fd20fc401
--- /dev/null
+++ b/include/download-instructions/osx-homebrew-php.php
@@ -0,0 +1,12 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Download and install Homebrew.
+curl -o- https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | 
bash
+
+# Install and link PHP.
+brew install shivammathur/php/php@<?= $version; ?>
+
+brew link --force --overwrite php@<?= $version; ?>
+</code></pre>
diff --git a/include/download-instructions/osx-homebrew.php 
b/include/download-instructions/osx-homebrew.php
new file mode 100644
index 0000000000..bc2f033cac
--- /dev/null
+++ b/include/download-instructions/osx-homebrew.php
@@ -0,0 +1,12 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Download and install Homebrew.
+curl -o- https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | 
bash
+
+# Install and link PHP.
+brew install php@<?= $version; ?>
+
+brew link --force --overwrite php@<?= $version; ?>
+</code></pre>
diff --git a/include/download-instructions/osx-macports.php 
b/include/download-instructions/osx-macports.php
new file mode 100644
index 0000000000..057c940465
--- /dev/null
+++ b/include/download-instructions/osx-macports.php
@@ -0,0 +1,7 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-bash line-numbers">
+# Please refer to https://guide.macports.org/chunked/installing.macports.html 
for installing MacPorts.
+sudo port install php<?= $versionNoDot; ?>
+</code></pre>
diff --git a/include/download-instructions/osx-source.php 
b/include/download-instructions/osx-source.php
new file mode 100644
index 0000000000..aa81b80171
--- /dev/null
+++ b/include/download-instructions/osx-source.php
@@ -0,0 +1,4 @@
+<p>
+       The <a 
href="https://www.php.net/manual/en/install.unix.source.php";>instructions for 
compiling from source
+       on macOS</a> are described in the PHP manual.
+</p>
diff --git a/include/download-instructions/windows-chocolatey.php 
b/include/download-instructions/windows-chocolatey.php
new file mode 100644
index 0000000000..56c6205465
--- /dev/null
+++ b/include/download-instructions/windows-chocolatey.php
@@ -0,0 +1,10 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-powershell line-numbers">
+# Download and install Chocolatey.
+powershell -c "irm https://community.chocolatey.org/install.ps1|iex"
+
+# Download and install PHP.
+choco install php --version=<?= $version; ?> -y
+</code></pre>
diff --git a/include/download-instructions/windows-native.php 
b/include/download-instructions/windows-native.php
new file mode 100644
index 0000000000..23e0e118cc
--- /dev/null
+++ b/include/download-instructions/windows-native.php
@@ -0,0 +1,7 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-powershell line-numbers">
+# Download and install PHP.
+powershell -c "& ([ScriptBlock]::Create((irm 
'https://www.php.net/include/download-instructions/windows.ps1'))) -Version <?= 
$version; ?>"
+</code></pre>
diff --git a/include/download-instructions/windows-scoop.php 
b/include/download-instructions/windows-scoop.php
new file mode 100644
index 0000000000..b95b7d1992
--- /dev/null
+++ b/include/download-instructions/windows-scoop.php
@@ -0,0 +1,11 @@
+<p>
+On the command line, run the following commands:
+</p>
+<pre><code class="language-powershell line-numbers">
+# Download and install Scoop.
+powershell -c "irm https://get.scoop.sh | iex"
+
+# Download and install PHP.
+scoop bucket add versions
+scoop install php<?= $versionNoDot; ?>
+</code></pre>
diff --git a/include/download-instructions/windows-source.php 
b/include/download-instructions/windows-source.php
new file mode 100644
index 0000000000..beacab7f70
--- /dev/null
+++ b/include/download-instructions/windows-source.php
@@ -0,0 +1,4 @@
+<p>
+       The <a 
href="https://www.php.net/manual/en/install.windows.building.php";>instructions 
for compiling from source
+       on Windows</a> are described in the PHP manual.
+</p>
diff --git a/include/download-instructions/windows.ps1 
b/include/download-instructions/windows.ps1
new file mode 100644
index 0000000000..d6ac1bad52
--- /dev/null
+++ b/include/download-instructions/windows.ps1
@@ -0,0 +1,228 @@
+<#
+.SYNOPSIS
+Downloads and sets up a specified PHP version on Windows.
+
+.PARAMETER Version
+Major.minor or full version (e.g., 7.4 or 7.4.30).
+
+.PARAMETER Path
+Destination directory (defaults to C:\php<Version>).
+
+.PARAMETER Arch
+Architecture: x64 or x86 (default: x64).
+
+.PARAMETER ThreadSafe
+ThreadSafe: download Thread Safe build (default: $False).
+
+.PARAMETER Timezone
+date.timezone string for php.ini (default: 'UTC').
+#>
+
+[CmdletBinding()]
+param(
+    [Parameter(Mandatory = $true, Position=0)]
+    [ValidatePattern('^\d+(\.\d+)?(\.\d+)?((alpha|beta|RC)\d*)?$')]
+    [string]$Version,
+    [Parameter(Mandatory = $false, Position=1)]
+    [string]$Path = "C:\php$Version",
+    [Parameter(Mandatory = $false, Position=2)]
+    [ValidateSet("x64", "x86")]
+    [string]$Arch = "x64",
+    [Parameter(Mandatory = $false, Position=3)]
+    [bool]$ThreadSafe = $False,
+    [Parameter(Mandatory = $false, Position=4)]
+    [string]$Timezone = 'UTC'
+)
+
+Function Get-File {
+    param (
+        [Parameter(Mandatory = $true, Position=0)]
+        [ValidateNotNullOrEmpty()]
+        [string] $Url,
+        [Parameter(Mandatory = $false, Position=1)]
+        [string] $FallbackUrl,
+        [Parameter(Mandatory = $false, Position=2)]
+        [string] $OutFile = '',
+        [Parameter(Mandatory = $false, Position=3)]
+        [int] $Retries = 3,
+        [Parameter(Mandatory = $false, Position=4)]
+        [int] $TimeoutSec = 0
+    )
+
+    for ($i = 0; $i -lt $Retries; $i++) {
+        try {
+            if($OutFile -ne '') {
+                Invoke-WebRequest -Uri $Url -OutFile $OutFile -TimeoutSec 
$TimeoutSec
+            } else {
+                Invoke-WebRequest -Uri $Url -TimeoutSec $TimeoutSec
+            }
+            break;
+        } catch {
+            if ($i -eq ($Retries - 1)) {
+                if($FallbackUrl) {
+                    try {
+                        if($OutFile -ne '') {
+                            Invoke-WebRequest -Uri $FallbackUrl -OutFile 
$OutFile -TimeoutSec $TimeoutSec
+                        } else {
+                            Invoke-WebRequest -Uri $FallbackUrl -TimeoutSec 
$TimeoutSec
+                        }
+                    } catch {
+                        throw "Failed to download the file from $Url and 
$FallbackUrl"
+                    }
+                } else {
+                    throw "Failed to download the file from $Url"
+                }
+            }
+        }
+    }
+}
+
+Function Get-Semver {
+    [CmdletBinding()]
+    param(
+        [Parameter(Mandatory = $true, Position=0)]
+        [ValidateNotNull()]
+        [ValidatePattern('^\d+\.\d+$')]
+        [string]$Version
+    )
+    $releases = Get-File -Url 
"https://downloads.php.net/~windows/releases/releases.json"; | ConvertFrom-Json
+    $semver = $releases.$Version.version
+    if($null -eq $semver) {
+        $semver = (Get-File -Url 
"https://downloads.php.net/~windows/releases/archives";).Links |
+                Where-Object { $_.href -match "php-($Version.[0-9]+).*" } |
+                ForEach-Object { $matches[1] } |
+                Sort-Object { [System.Version]$_ } -Descending |
+                Select-Object -First 1
+    }
+    if($null -eq $semver) {
+        throw "Unsupported PHP version: $Version"
+    }
+    return $semver
+}
+
+Function Get-VSVersion {
+    param(
+        [Parameter(Mandatory = $true, Position=0)]
+        [ValidateNotNull()]
+        [ValidatePattern('^\d+\.\d+$')]
+        [string]$Version
+    )
+    $map = @{
+        '5.2' = 'VC6'
+        '5.3' = 'VC9'; '5.4' = 'VC9'
+        '5.5' = 'VC11'; '5.6' = 'VC11'
+        '7.0' = 'VC14'; '7.1' = 'VC14'
+        '7.2' = 'VC15'; '7.3' = 'VC15'; '7.4' = 'vc15'
+        '8.0' = 'vs16'; '8.1' = 'vs16'; '8.2' = 'vs16'; '8.3' = 'vs16'
+        '8.4' = 'vs17'; '8.5' = 'vs17'
+    }
+
+    if ($map.ContainsKey($Version)) {
+        return $map[$Version]
+    }
+    throw "Unsupported PHP version: $Version"
+}
+
+Function Get-ReleaseType {
+    param(
+        [Parameter(Mandatory = $true, Position=0)]
+        [ValidateNotNull()]
+        [ValidatePattern('^\d+(\.\d+)?(\.\d+)?((alpha|beta|RC)\d*)?$')]
+        [string]$Version
+    )
+    if ($Version -match "[a-zA-Z]") {
+        return "qa"
+    } else {
+        return "releases"
+    }
+}
+
+Function Get-PhpFromUrl {
+    param(
+        [Parameter(Mandatory = $true, Position=0)]
+        [ValidateNotNull()]
+        [ValidatePattern('^\d+\.\d+$')]
+        [string]$Version,
+        [Parameter(Mandatory = $true, Position=1)]
+        [ValidateNotNull()]
+        [ValidatePattern('^\d+(\.\d+)?(\.\d+)?((alpha|beta|RC)\d*)?$')]
+        [string]$Semver,
+        [Parameter(Mandatory = $false, Position=2)]
+        [ValidateSet("x64", "x86")]
+        [string]$Arch = "x64",
+        [Parameter(Mandatory = $false, Position=3)]
+        [bool]$ThreadSafe = $false,
+        [Parameter(Mandatory = $true, Position=4)]
+        [ValidateNotNull()]
+        [ValidateLength(1, [int]::MaxValue)]
+        [string]$OutFile
+    )
+    $vs = Get-VSVersion $Version
+    $ts = if ($ThreadSafe) { "ts" } else { "nts" }
+    $zipName = if ($ThreadSafe) { "php-$Semver-Win32-$vs-$Arch.zip" } else { 
"php-$Semver-$ts-Win32-$vs-$Arch.zip" }
+    $type = Get-ReleaseType $Version
+
+    $base = "https://downloads.php.net/~windows/$type";
+    try {
+        Get-File -Url "$base/$zipName" -OutFile $OutFile
+    } catch {
+        try {
+            Get-File -Url "$base/archives/$zipName" -OutFile $OutFile
+        } catch {
+            throw "Failed to download PHP $Semver."
+        }
+    }
+}
+
+$tempFile = [IO.Path]::ChangeExtension([IO.Path]::GetTempFileName(), '.zip')
+try {
+    if ($Version -match "^\d+\.\d+$") {
+        $Semver = Get-Semver $Version
+    } else {
+        $Semver = $Version
+        $Semver -match '^(\d+\.\d+)' | Out-Null
+        $Version = $Matches[1]
+    }
+
+    if (-not (Test-Path $Path)) {
+        try {
+            New-Item -ItemType Directory -Path $Path -ErrorAction Stop | 
Out-Null
+        } catch {
+            throw "Failed to create directory $Path. $_"
+        }
+    } else {
+        $files = Get-ChildItem -Path $Path
+        if ($files.Count -gt 0) {
+            throw "The directory $Path is not empty. Please provide an empty 
directory."
+        }
+    }
+
+    if($Version -lt '5.5' -and $Arch -eq 'x64') {
+        $Arch = 'x86'
+        Write-Host "PHP version $Version does not support x64 architecture on 
Windows. Using x86 instead."
+    }
+
+    Write-Host "Downloading PHP $Semver to $Path"
+    Get-PhpFromUrl $Version $Semver $Arch $ThreadSafe $tempFile
+    Expand-Archive -Path $tempFile -DestinationPath $Path -Force -ErrorAction 
Stop
+
+    $phpIniProd = Join-Path $Path "php.ini-production"
+    if(-not(Test-Path $phpIniProd)) {
+        $phpIniProd = Join-Path $Path "php.ini-recommended"
+    }
+    $phpIni = Join-Path $Path "php.ini"
+    Copy-Item $phpIniProd $phpIni -Force
+    $extensionDir = Join-Path $Path "ext"
+    (Get-Content $phpIni) -replace '^extension_dir = "./"', "extension_dir = 
`"$extensionDir`"" | Set-Content $phpIni
+    (Get-Content $phpIni) -replace ';\s?extension_dir = "ext"', "extension_dir 
= `"$extensionDir`"" | Set-Content $phpIni
+    (Get-Content $phpIni) -replace ';\s?date.timezone =', "date.timezone = 
`"$Timezone`"" | Set-Content $phpIni
+
+    Write-Host "PHP $Semver downloaded to $Path"
+} catch {
+    Write-Error $_
+    Exit 1
+} finally {
+    if (Test-Path $tempFile) {
+        Remove-Item $tempFile -Force -ErrorAction SilentlyContinue
+    }
+}
diff --git a/include/header.inc b/include/header.inc
index c31b73ebad..3da277344c 100644
--- a/include/header.inc
+++ b/include/header.inc
@@ -23,6 +23,14 @@ foreach($css_files as $filename) {
     $CSS[$filename] = @filemtime($path);
 }
 
+$JS = [];
+if (isset($config["js_files"])) {
+    foreach($config['js_files'] as $filename) {
+        $path = dirname(__DIR__) . '/' . $filename;
+        $JS[$filename] = @filemtime($path);
+    }
+}
+
 if (isset($shortname) && $shortname) {
     header("Link: <$shorturl>; rel=shorturl");
 }
@@ -89,6 +97,18 @@ if (!isset($config["languages"])) {
  <link rel="alternate" href="<?php echo $MYSITE ?>manual/<?php echo 
$code?>/<?php echo $config["thispage"] ?>" hreflang="<?php echo $code?>">
 <?php endforeach ?>
 
+<?php foreach($CSS as $filename => $modified): ?>
+<link rel="stylesheet" type="text/css" href="/cached.php?t=<?php echo 
$modified?>&amp;f=<?php echo $filename?>" media="screen">
+<?php endforeach ?>
+
+<?php foreach($JS as $filename => $modified): ?>
+<script type="text/javascript" src="/cached.php?t=<?php echo 
$modified?>&amp;f=<?php echo $filename?>"></script>
+<?php endforeach ?>
+
+<?php if (!empty($_SERVER["BASE_HREF"])): ?>
+ <base href="<?php echo $_SERVER["BASE_HREF"] ?>">
+<?php endif ?>
+
 <?php if (isset($config['meta_tags'])) { echo $config['meta_tags']; } ?>
 
 <?php if (is_primary_site()) { ?>
diff --git a/include/version.inc b/include/version.inc
index 5c039b63a8..75d9a16f91 100644
--- a/include/version.inc
+++ b/include/version.inc
@@ -107,3 +107,55 @@ function release_get_latest() {
 
     return [$version, $current];
 }
+
+function show_source_releases()
+{
+    global $RELEASES;
+
+    $SHOW_COUNT = 4;
+
+    $i = 0; foreach ($RELEASES as $MAJOR => $major_releases): /* major 
releases loop start */
+        $releases = array_slice($major_releases, 0, $SHOW_COUNT);
+?>
+        <a id="v<?php echo $MAJOR; ?>"></a>
+        <?php foreach ($releases as $v => $a): ?>
+          <?php $mver = substr($v, 0, strrpos($v, '.')); ?>
+          <?php $stable = $i++ === 0 ? "Current Stable" : "Old Stable"; ?>
+
+          <h3 id="v<?php echo $v; ?>" class="title">
+            <span class="release-state"><?php echo $stable; ?></span>
+            PHP <?php echo $v; ?>
+            (<a href="/ChangeLog-<?php echo $MAJOR; ?>.php#<?php echo 
urlencode($v); ?>" class="changelog">Changelog</a>)
+          </h3>
+          <div class="content-box">
+
+            <ul>
+              <?php foreach ($a['source'] as $rel): ?>
+                <li>
+                  <?php download_link($rel['filename'], $rel['filename']); ?>
+                  <span class="releasedate"><?php echo date('d M Y', 
strtotime($rel['date'])); ?></span>
+                  <?php
+                    if (isset($rel['md5']))    echo '<span class="md5sum">', 
$rel['md5'], '</span>';
+                    if (isset($rel['sha256'])) echo '<span class="sha256">', 
$rel['sha256'], '</span>';
+                   ?>
+                  <?php if (isset($rel['note']) && $rel['note']): ?>
+                    <p>
+                      <strong>Note:</strong>
+                      <?php echo $rel['note']; ?>
+                    </p>
+                  <?php endif; ?>
+                </li>
+              <?php endforeach; ?>
+              <li>
+                <a href="https://windows.php.net/download#php-<?php echo 
urlencode($mver); ?>">
+                  Windows downloads
+                </a>
+              </li>
+            </ul>
+
+            <a href="#gpg-<?php echo $mver; ?>">GPG Keys for PHP <?php echo 
$mver; ?></a>
+          </div>
+        <?php endforeach; ?>
+    <?php endforeach; /* major releases loop end */ ?>
+<?php
+}
diff --git a/js/ext/prism.js b/js/ext/prism.js
new file mode 100644
index 0000000000..81c919284d
--- /dev/null
+++ b/js/ext/prism.js
@@ -0,0 +1,10 @@
+/* PrismJS 1.30.0
+https://prismjs.com/download#themes=prism&languages=bash+powershell&plugins=line-numbers+show-language+remove-initial-line-feed+toolbar+copy-to-clipboard
 */
+var _self="undefined"!=typeof window?window:"undefined"!=typeof 
WorkerGlobalScope&&self instanceof 
WorkerGlobalScope?self:{},Prism=function(e){var 
n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function
 e(n){return n instanceof i?new 
i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g,"
 ")},type:function(e){return 
Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return 
e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function 
e(n,t){var 
r,i;switch(t=t||{},a.util.type(n)){case"Object":if(i=a.util.objId(n),t[i])return
 t[i];for(var l in r={},t[i]=r,n)n.hasOwnProperty(l)&&(r[l]=e(n[l],t));return 
r;case"Array":return 
i=a.util.objId(n),t[i]?t[i]:(r=[],t[i]=r,n.forEach((function(n,a){r[a]=e(n,t)})),r);default:return
 n}},getLanguage:function(e){for(;e;){var t=n.exec(e.className);if(t)return 
t[1].toLowerCase();e=e.parentElement}return"none"},setLanguage:function(e,t){e.className=e.className.replace(RegExp(n,"gi"),""),e.classList.add("language-"+t)},currentScript:function(){if("undefined"==typeof
 document)return 
null;if(document.currentScript&&"SCRIPT"===document.currentScript.tagName)return
 document.currentScript;try{throw new Error}catch(r){var e=(/at 
[^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(r.stack)||[])[1];if(e){var 
n=document.getElementsByTagName("script");for(var t in n)if(n[t].src==e)return 
n[t]}return null}},isActive:function(e,n,t){for(var r="no-"+n;e;){var 
a=e.classList;if(a.contains(n))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!t}},languages:{plain:r,plaintext:r,text:r,txt:r,extend:function(e,n){var
 t=a.util.clone(a.languages[e]);for(var r in n)t[r]=n[r];return 
t},insertBefore:function(e,n,t,r){var i=(r=r||a.languages)[e],l={};for(var o in 
i)if(i.hasOwnProperty(o)){if(o==n)for(var s in 
t)t.hasOwnProperty(s)&&(l[s]=t[s]);t.hasOwnProperty(o)||(l[o]=i[o])}var 
u=r[e];return 
r[e]=l,a.languages.DFS(a.languages,(function(n,t){t===u&&n!=e&&(this[n]=l)})),l},DFS:function
 e(n,t,r,i){i=i||{};var l=a.util.objId;for(var o in 
n)if(n.hasOwnProperty(o)){t.call(n,o,n[o],r||o);var 
s=n[o],u=a.util.type(s);"Object"!==u||i[l(s)]?"Array"!==u||i[l(s)]||(i[l(s)]=!0,e(s,t,o,i)):(i[l(s)]=!0,e(s,t,null,i))}}},plugins:{},highlightAll:function(e,n){a.highlightAllUnder(document,e,n)},highlightAllUnder:function(e,n,t){var
 r={callback:t,container:e,selector:'code[class*="language-"], 
[class*="language-"] code, code[class*="lang-"], [class*="lang-"] 
code'};a.hooks.run("before-highlightall",r),r.elements=Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)),a.hooks.run("before-all-elements-highlight",r);for(var
 
i,l=0;i=r.elements[l++];)a.highlightElement(i,!0===n,r.callback)},highlightElement:function(n,t,r){var
 i=a.util.getLanguage(n),l=a.languages[i];a.util.setLanguage(n,i);var 
o=n.parentElement;o&&"pre"===o.nodeName.toLowerCase()&&a.util.setLanguage(o,i);var
 s={element:n,language:i,grammar:l,code:n.textContent};function 
u(e){s.highlightedCode=e,a.hooks.run("before-insert",s),s.element.innerHTML=s.highlightedCode,a.hooks.run("after-highlight",s),a.hooks.run("complete",s),r&&r.call(s.element)}if(a.hooks.run("before-sanity-check",s),(o=s.element.parentElement)&&"pre"===o.nodeName.toLowerCase()&&!o.hasAttribute("tabindex")&&o.setAttribute("tabindex","0"),!s.code)return
 
a.hooks.run("complete",s),void(r&&r.call(s.element));if(a.hooks.run("before-highlight",s),s.grammar)if(t&&e.Worker){var
 c=new 
Worker(a.filename);c.onmessage=function(e){u(e.data)},c.postMessage(JSON.stringify({language:s.language,code:s.code,immediateClose:!0}))}else
 u(a.highlight(s.code,s.grammar,s.language));else 
u(a.util.encode(s.code))},highlight:function(e,n,t){var 
r={code:e,grammar:n,language:t};if(a.hooks.run("before-tokenize",r),!r.grammar)throw
 new Error('The language "'+r.language+'" has no grammar.');return 
r.tokens=a.tokenize(r.code,r.grammar),a.hooks.run("after-tokenize",r),i.stringify(a.util.encode(r.tokens),r.language)},tokenize:function(e,n){var
 t=n.rest;if(t){for(var r in t)n[r]=t[r];delete n.rest}var a=new s;return 
u(a,a.head,e),o(e,a,n,a.head,0),function(e){for(var 
n=[],t=e.head.next;t!==e.tail;)n.push(t.value),t=t.next;return 
n}(a)},hooks:{all:{},add:function(e,n){var 
t=a.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var 
t=a.hooks.all[e];if(t&&t.length)for(var 
r,i=0;r=t[i++];)r(n)}},Token:i};function 
i(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||"").length}function
 l(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var 
i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function 
o(e,n,t,r,s,g){for(var f in t)if(t.hasOwnProperty(f)&&t[f]){var 
h=t[f];h=Array.isArray(h)?h:[h];for(var 
d=0;d<h.length;++d){if(g&&g.cause==f+","+d)return;var 
v=h[d],p=v.inside,m=!!v.lookbehind,y=!!v.greedy,k=v.alias;if(y&&!v.pattern.global){var
 
x=v.pattern.toString().match(/[imsuy]*$/)[0];v.pattern=RegExp(v.pattern.source,x+"g")}for(var
 
b=v.pattern||v,w=r.next,A=s;w!==n.tail&&!(g&&A>=g.reach);A+=w.value.length,w=w.next){var
 P=w.value;if(n.length>e.length)return;if(!(P instanceof i)){var 
E,S=1;if(y){if(!(E=l(b,A,e,m))||E.index>=e.length)break;var 
L=E.index,O=E.index+E[0].length,C=A;for(C+=w.value.length;L>=C;)C+=(w=w.next).value.length;if(A=C-=w.value.length,w.value
 instanceof i)continue;for(var j=w;j!==n.tail&&(C<O||"string"==typeof 
j.value);j=j.next)S++,C+=j.value.length;S--,P=e.slice(A,C),E.index-=A}else 
if(!(E=l(b,0,P,m)))continue;L=E.index;var 
N=E[0],_=P.slice(0,L),M=P.slice(L+N.length),W=A+P.length;g&&W>g.reach&&(g.reach=W);var
 I=w.prev;if(_&&(I=u(n,I,_),A+=_.length),c(n,I,S),w=u(n,I,new 
i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),S>1){var 
T={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,T),g&&T.reach>g.reach&&(g.reach=T.reach)}}}}}}function
 s(){var 
e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function
 u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return 
n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var 
r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;n.next=r,r.prev=n,e.length-=a}if(e.Prism=a,i.stringify=function
 e(n,t){if("string"==typeof n)return n;if(Array.isArray(n)){var r="";return 
n.forEach((function(n){r+=e(n,t)})),r}var 
i={type:n.type,content:e(n.content,t),tag:"span",classes:["token",n.type],attributes:{},language:t},l=n.alias;l&&(Array.isArray(l)?Array.prototype.push.apply(i.classes,l):i.classes.push(l)),a.hooks.run("wrap",i);var
 o="";for(var s in i.attributes)o+=" 
"+s+'="'+(i.attributes[s]||"").replace(/"/g,"&quot;")+'"';return"<"+i.tag+' 
class="'+i.classes.join(" 
")+'"'+o+">"+i.content+"</"+i.tag+">"},!e.document)return 
e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var
 
t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var
 g=a.util.currentScript();function 
f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var
 
h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return
 a}(_self);"undefined"!=typeof 
module&&module.exports&&(module.exports=Prism),"undefined"!=typeof 
global&&(global.Prism=Prism);
+!function(e){var 
t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",a={pattern:/(^(["']?)\w+\2)[
 
\t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},n={bash:a,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:a}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:n},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:n.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},a.inside=e.languages.bash;for(var
 
s=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=n.variable[1].inside,i=0;i<s.length;i++)o[s[i]]=e.languages.bash[s[i]];e.languages.sh=e.languages.bash,e.languages.shell=e.languages.bash}(Prism);
+!function(e){var 
i=e.languages.powershell={comment:[{pattern:/(^|[^`])<#[\s\S]*?#>/,lookbehind:!0},{pattern:/(^|[^`])#.*/,lookbehind:!0}],string:[{pattern:/"(?:`[\s\S]|[^`"])*"/,greedy:!0,inside:null},{pattern:/'(?:[^']|'')*'/,greedy:!0}],namespace:/\[[a-z](?:\[(?:\[[^\]]*\]|[^\[\]])*\]|[^\[\]])*\]/i,boolean:/\$(?:false|true)\b/i,variable:/\$\w+\b/,function:[/\b(?:Add|Approve|Assert|Backup|Block|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|ForEach|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Sort|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Tee|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Where|Write)-[a-z]+\b/i,/\b(?:ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i],keyword:/\b(?:Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,operator:{pattern:/(^|\W)(?:!|-(?:b?(?:and|x?or)|as|(?:Not)?(?:Contains|In|Like|Match)|eq|ge|gt|is(?:Not)?|Join|le|lt|ne|not|Replace|sh[lr])\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,lookbehind:!0},punctuation:/[|{}[\];(),.]/};i.string[0].inside={function:{pattern:/(^|[^`])\$\((?:\$\([^\r\n()]*\)|(?!\$\()[^\r\n)])*\)/,lookbehind:!0,inside:i},boolean:i.boolean,variable:i.variable}}(Prism);
+!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var 
e="line-numbers",n=/\n(?!$)/g,t=Prism.plugins.lineNumbers={getLine:function(n,t){if("PRE"===n.tagName&&n.classList.contains(e)){var
 i=n.querySelector(".line-numbers-rows");if(i){var 
r=parseInt(n.getAttribute("data-start"),10)||1,s=r+(i.children.length-1);t<r&&(t=r),t>s&&(t=s);var
 l=t-r;return 
i.children[l]}}},resize:function(e){r([e])},assumeViewportIndependence:!0},i=void
 
0;window.addEventListener("resize",(function(){t.assumeViewportIndependence&&i===window.innerWidth||(i=window.innerWidth,r(Array.prototype.slice.call(document.querySelectorAll("pre.line-numbers"))))})),Prism.hooks.add("complete",(function(t){if(t.code){var
 
i=t.element,s=i.parentNode;if(s&&/pre/i.test(s.nodeName)&&!i.querySelector(".line-numbers-rows")&&Prism.util.isActive(i,e)){i.classList.remove(e),s.classList.add(e);var
 l,o=t.code.match(n),a=o?o.length+1:1,u=new 
Array(a+1).join("<span></span>");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=u,s.hasAttribute("data-start")&&(s.style.counterReset="linenumber
 
"+(parseInt(s.getAttribute("data-start"),10)-1)),t.element.appendChild(l),r([s]),Prism.hooks.run("line-numbers",t)}}})),Prism.hooks.add("line-numbers",(function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}))}function
 r(e){if(0!=(e=e.filter((function(e){var 
n,t=(n=e,n?window.getComputedStyle?getComputedStyle(n):n.currentStyle||null:null)["white-space"];return"pre-wrap"===t||"pre-line"===t}))).length){var
 t=e.map((function(e){var 
t=e.querySelector("code"),i=e.querySelector(".line-numbers-rows");if(t&&i){var 
r=e.querySelector(".line-numbers-sizer"),s=t.textContent.split(n);r||((r=document.createElement("span")).className="line-numbers-sizer",t.appendChild(r)),r.innerHTML="0",r.style.display="block";var
 l=r.getBoundingClientRect().height;return 
r.innerHTML="",{element:e,lines:s,lineHeights:[],oneLinerHeight:l,sizer:r}}})).filter(Boolean);t.forEach((function(e){var
 n=e.sizer,t=e.lines,i=e.lineHeights,r=e.oneLinerHeight;i[t.length-1]=void 
0,t.forEach((function(e,t){if(e&&e.length>1){var 
s=n.appendChild(document.createElement("span"));s.style.display="block",s.textContent=e}else
 i[t]=r}))})),t.forEach((function(e){for(var 
n=e.sizer,t=e.lineHeights,i=0,r=0;r<t.length;r++)void 
0===t[r]&&(t[r]=n.children[i++].getBoundingClientRect().height)})),t.forEach((function(e){var
 
n=e.sizer,t=e.element.querySelector(".line-numbers-rows");n.style.display="none",n.innerHTML="",e.lineHeights.forEach((function(e,n){t.children[n].style.height=e+"px"}))}))}}}();
+!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var 
e=[],t={},n=function(){};Prism.plugins.toolbar={};var 
a=Prism.plugins.toolbar.registerButton=function(n,a){var r;r="function"==typeof 
a?a:function(e){var t;return"function"==typeof 
a.onClick?((t=document.createElement("button")).type="button",t.addEventListener("click",(function(){a.onClick.call(this,e)}))):"string"==typeof
 
a.url?(t=document.createElement("a")).href=a.url:t=document.createElement("span"),a.className&&t.classList.add(a.className),t.textContent=a.text,t},n
 in t?console.warn('There is a button with the key "'+n+'" registered 
already.'):e.push(t[n]=r)},r=Prism.plugins.toolbar.hook=function(a){var 
r=a.element.parentNode;if(r&&/pre/i.test(r.nodeName)&&!r.parentNode.classList.contains("code-toolbar")){var
 
o=document.createElement("div");o.classList.add("code-toolbar"),r.parentNode.insertBefore(o,r),o.appendChild(r);var
 i=document.createElement("div");i.classList.add("toolbar");var 
l=e,d=function(e){for(;e;){var 
t=e.getAttribute("data-toolbar-order");if(null!=t)return(t=t.trim()).length?t.split(/\s*,\s*/g):[];e=e.parentElement}}(a.element);d&&(l=d.map((function(e){return
 t[e]||n}))),l.forEach((function(e){var t=e(a);if(t){var 
n=document.createElement("div");n.classList.add("toolbar-item"),n.appendChild(t),i.appendChild(n)}})),o.appendChild(i)}};a("label",(function(e){var
 
t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute("data-label")){var
 
n,a,r=t.getAttribute("data-label");try{a=document.querySelector("template#"+r)}catch(e){}return
 
a?n=a.content:(t.hasAttribute("data-url")?(n=document.createElement("a")).href=t.getAttribute("data-url"):n=document.createElement("span"),n.textContent=r),n}})),Prism.hooks.add("complete",r)}}();
+!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof 
document)if(Prism.plugins.toolbar){var e={none:"Plain text",plain:"Plain 
text",plaintext:"Plain text",text:"Plain text",txt:"Plain 
text",html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",rss:"RSS",css:"CSS",clike:"C-like",js:"JavaScript",abap:"ABAP",abnf:"ABNF",al:"AL",antlr4:"ANTLR4",g4:"ANTLR4",apacheconf:"Apache
 Configuration",apl:"APL",aql:"AQL",ino:"Arduino",arff:"ARFF",armasm:"ARM 
Assembly","arm-asm":"ARM 
Assembly",art:"Arturo",asciidoc:"AsciiDoc",adoc:"AsciiDoc",aspnet:"ASP.NET 
(C#)",asm6502:"6502 Assembly",asmatmel:"Atmel AVR 
Assembly",autohotkey:"AutoHotkey",autoit:"AutoIt",avisynth:"AviSynth",avs:"AviSynth","avro-idl":"Avro
 IDL",avdl:"Avro 
IDL",awk:"AWK",gawk:"GAWK",sh:"Shell",basic:"BASIC",bbcode:"BBcode",bbj:"BBj",bnf:"BNF",rbnf:"RBNF",bqn:"BQN",bsl:"BSL
 
(1C:Enterprise)",oscript:"OneScript",csharp:"C#",cs:"C#",dotnet:"C#",cpp:"C++",cfscript:"CFScript",cfc:"CFScript",cil:"CIL",cilkc:"Cilk/C","cilk-c":"Cilk/C",cilkcpp:"Cilk/C++","cilk-cpp":"Cilk/C++",cilk:"Cilk/C++",cmake:"CMake",cobol:"COBOL",coffee:"CoffeeScript",conc:"Concurnas",csp:"Content-Security-Policy","css-extras":"CSS
 
Extras",csv:"CSV",cue:"CUE",dataweave:"DataWeave",dax:"DAX",django:"Django/Jinja2",jinja2:"Django/Jinja2","dns-zone-file":"DNS
 zone file","dns-zone":"DNS zone file",dockerfile:"Docker",dot:"DOT 
(Graphviz)",gv:"DOT 
(Graphviz)",ebnf:"EBNF",editorconfig:"EditorConfig",ejs:"EJS",etlua:"Embedded 
Lua templating",erb:"ERB","excel-formula":"Excel Formula",xlsx:"Excel 
Formula",xls:"Excel Formula",fsharp:"F#","firestore-security-rules":"Firestore 
security rules",ftl:"FreeMarker Template Language",gml:"GameMaker 
Language",gamemakerlanguage:"GameMaker Language",gap:"GAP 
(CAS)",gcode:"G-code",gdscript:"GDScript",gedcom:"GEDCOM",gettext:"gettext",po:"gettext",glsl:"GLSL",gn:"GN",gni:"GN","linker-script":"GNU
 Linker Script",ld:"GNU Linker Script","go-module":"Go module","go-mod":"Go 
module",graphql:"GraphQL",hbs:"Handlebars",hs:"Haskell",hcl:"HCL",hlsl:"HLSL",http:"HTTP",hpkp:"HTTP
 Public-Key-Pins",hsts:"HTTP 
Strict-Transport-Security",ichigojam:"IchigoJam","icu-message-format":"ICU 
Message 
Format",idr:"Idris",ignore:".ignore",gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore",inform7:"Inform
 7",javadoc:"JavaDoc",javadoclike:"JavaDoc-like",javastacktrace:"Java stack 
trace",jq:"JQ",jsdoc:"JSDoc","js-extras":"JS 
Extras",json:"JSON",webmanifest:"Web App 
Manifest",json5:"JSON5",jsonp:"JSONP",jsstacktrace:"JS stack 
trace","js-templates":"JS Templates",keepalived:"Keepalived 
Configure",kts:"Kotlin Script",kt:"Kotlin",kumir:"KuMir (КуМир)",kum:"KuMir 
(КуМир)",latex:"LaTeX",tex:"TeX",context:"ConTeXt",lilypond:"LilyPond",ly:"LilyPond",emacs:"Lisp",elisp:"Lisp","emacs-lisp":"Lisp",llvm:"LLVM
 IR",log:"Log file",lolcode:"LOLCODE",magma:"Magma 
(CAS)",md:"Markdown","markup-templating":"Markup 
templating",matlab:"MATLAB",maxscript:"MAXScript",mel:"MEL",metafont:"METAFONT",mongodb:"MongoDB",moon:"MoonScript",n1ql:"N1QL",n4js:"N4JS",n4jsd:"N4JS","nand2tetris-hdl":"Nand
 To Tetris HDL",naniscript:"Naninovel Script",nani:"Naninovel 
Script",nasm:"NASM",neon:"NEON",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",objc:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",openqasm:"OpenQasm",qasm:"OpenQasm",parigp:"PARI/GP",objectpascal:"Object
 Pascal",psl:"PATROL Scripting 
Language",pcaxis:"PC-Axis",px:"PC-Axis",peoplecode:"PeopleCode",pcode:"PeopleCode",php:"PHP",phpdoc:"PHPDoc","php-extras":"PHP
 
Extras","plant-uml":"PlantUML",plantuml:"PlantUML",plsql:"PL/SQL",powerquery:"PowerQuery",pq:"PowerQuery",mscript:"PowerQuery",powershell:"PowerShell",promql:"PromQL",properties:".properties",protobuf:"Protocol
 
Buffers",purebasic:"PureBasic",pbfasm:"PureBasic",purs:"PureScript",py:"Python",qsharp:"Q#",qs:"Q#",q:"Q
 (kdb+ database)",qml:"QML",rkt:"Racket",cshtml:"Razor C#",razor:"Razor 
C#",jsx:"React JSX",tsx:"React 
TSX",renpy:"Ren'py",rpy:"Ren'py",res:"ReScript",rest:"reST 
(reStructuredText)",robotframework:"Robot Framework",robot:"Robot 
Framework",rb:"Ruby",sas:"SAS",sass:"Sass (Sass)",scss:"Sass 
(SCSS)","shell-session":"Shell session","sh-session":"Shell 
session",shellsession:"Shell 
session",sml:"SML",smlnj:"SML/NJ",solidity:"Solidity (Ethereum)",sol:"Solidity 
(Ethereum)","solution-file":"Solution file",sln:"Solution file",soy:"Soy 
(Closure Template)",sparql:"SPARQL",rq:"SPARQL","splunk-spl":"Splunk 
SPL",sqf:"SQF: Status Quo Function (Arma 3)",sql:"SQL",stata:"Stata 
Ado",iecst:"Structured Text (IEC 
61131-3)",supercollider:"SuperCollider",sclang:"SuperCollider",systemd:"Systemd 
configuration file","t4-templating":"T4 templating","t4-cs":"T4 Text Templates 
(C#)",t4:"T4 Text Templates (C#)","t4-vb":"T4 Text Templates 
(VB)",tap:"TAP",tt2:"Template Toolkit 
2",toml:"TOML",trickle:"trickle",troy:"troy",trig:"TriG",ts:"TypeScript",tsconfig:"TSConfig",uscript:"UnrealScript",uc:"UnrealScript",uorazor:"UO
 Razor 
Script",uri:"URI",url:"URL",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim","visual-basic":"Visual
 Basic",vba:"VBA",vb:"Visual Basic",wasm:"WebAssembly","web-idl":"Web 
IDL",webidl:"Web IDL",wgsl:"WGSL",wiki:"Wiki markup",wolfram:"Wolfram 
language",nb:"Mathematica Notebook",wl:"Wolfram 
language",xeoracube:"XeoraCube","xml-doc":"XML doc (.net)",xojo:"Xojo 
(REALbasic)",xquery:"XQuery",yaml:"YAML",yml:"YAML",yang:"YANG"};Prism.plugins.toolbar.registerButton("show-language",(function(a){var
 t=a.element.parentNode;if(t&&/pre/i.test(t.nodeName)){var 
o,i=t.getAttribute("data-language")||e[a.language]||((o=a.language)?(o.substring(0,1).toUpperCase()+o.substring(1)).replace(/s(?=cript)/,"S"):o);if(i){var
 s=document.createElement("span");return s.textContent=i,s}}}))}else 
console.warn("Show Languages plugin loaded before Toolbar plugin.")}();
+"undefined"!=typeof Prism&&"undefined"!=typeof 
document&&Prism.hooks.add("before-sanity-check",(function(e){if(e.code){var 
n=e.element.parentNode,o=/(?:^|\s)keep-initial-line-feed(?:\s|$)/;!n||"pre"!==n.nodeName.toLowerCase()||o.test(n.className)||o.test(e.element.className)||(e.code=e.code.replace(/^(?:\r?\n|\r)/,""))}}));
+!function(){function t(t){var 
e=document.createElement("textarea");e.value=t.getText(),e.style.top="0",e.style.left="0",e.style.position="fixed",document.body.appendChild(e),e.focus(),e.select();try{var
 
o=document.execCommand("copy");setTimeout((function(){o?t.success():t.error()}),1)}catch(e){setTimeout((function(){t.error(e)}),1)}document.body.removeChild(e)}"undefined"!=typeof
 Prism&&"undefined"!=typeof 
document&&(Prism.plugins.toolbar?Prism.plugins.toolbar.registerButton("copy-to-clipboard",(function(e){var
 o=e.element,n=function(t){var e={copy:"<svg xmlns='http://www.w3.org/2000/svg' 
width='16' height='16' viewBox='0 0 16 16' fill='currentColor' 
aria-hidden='true' style='vertical-align:middle; margin-right:4px'> <path 
d='M10 1H2a1 1 0 0 0-1 1v10h1V2h8V1zm3 2H4a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h9a1 1 
0 0 0 1-1V4a1 1 0 0 0-1-1zM4 4h9v11H4V4z'/></svg> Copy","copy-error":"Press 
Ctrl+C to copy","copy-success":"<svg xmlns='http://www.w3.org/2000/svg' 
width='16' height='16' viewBox='0 0 16 16' aria-hidden='true' 
style='vertical-align:middle;margin-right:.3em;'><path fill='#ffffff' d='M13.78 
4.22a.75.75 0 0 0-1.06 0L6.75 10.19 3.28 6.72a.75.75 0 1 0-1.06 1.06l4 4a.75.75 
0 0 0 1.06 0l6-6a.75.75 0 0 0 0-1.06z'/></svg> 
Copy","copy-timeout":5e3};for(var o in e){for(var 
n="data-prismjs-"+o,c=t;c&&!c.hasAttribute(n);)c=c.parentElement;c&&(e[o]=c.getAttribute(n))}return
 
e}(o),c=document.createElement("button");c.className="copy-to-clipboard-button",c.setAttribute("type","button");var
 r=document.createElement("span");return 
c.appendChild(r),u("copy"),function(e,o){e.addEventListener("click",(function(){!function(e){navigator.clipboard?navigator.clipboard.writeText(e.getText()).then(e.success,(function(){t(e)})):t(e)}(o)}))}(c,{getText:function(){return
 
o.textContent},success:function(){u("copy-success"),i()},error:function(){u("copy-error"),setTimeout((function(){!function(t){window.getSelection().selectAllChildren(t)}(o)}),1),i()}}),c;function
 i(){setTimeout((function(){u("copy")}),n["copy-timeout"])}function 
u(t){r.innerHTML=n[t],c.setAttribute("data-copy-state",t)}})):console.warn("Copy
 to Clipboard plugin loaded before Toolbar plugin."))}();
diff --git a/styles/code-syntax.css b/styles/code-syntax.css
new file mode 100644
index 0000000000..26dfdbf332
--- /dev/null
+++ b/styles/code-syntax.css
@@ -0,0 +1,65 @@
+pre[class*=language-] {
+    margin: 0;
+}
+
+:not(pre) > code[class*=language-], pre[class*=language-] {
+    background: transparent;
+}
+
+.code-toolbar .toolbar {
+    opacity: 1 !important;
+    visibility: visible !important;
+    pointer-events: auto !important;
+}
+
+div.code-toolbar > .toolbar {
+    position: relative;
+    border-top: 1px solid rgba(0, 0, 0, .15);
+    top: 0;
+    right: 0;
+    justify-content: space-between;
+    align-items: center;
+    display: flex;
+}
+
+.code-toolbar {
+    box-shadow: 0 0 0 1px rgba(0, 0, 0, .15);
+}
+
+.toolbar-item {
+    padding: 5px;
+}
+
+pre.line-numbers {
+    padding-left: 2.5em !important;
+}
+
+pre.line-numbers .line-numbers-rows {
+    border-right: none !important;
+    width: 4em !important;
+}
+
+pre.line-numbers .line-numbers-rows > span:before {
+    padding-right: 1em !important;
+}
+
+div.code-toolbar > .toolbar > .toolbar-item > a, div.code-toolbar > .toolbar > 
.toolbar-item > button, div.code-toolbar > .toolbar > .toolbar-item > span {
+    color: #000;
+    background: transparent;
+    box-shadow: none;
+    padding-left: 1em !important;
+}
+
+button.copy-to-clipboard-button {
+    padding: 0.75em !important;
+    padding-right: 1em !important;
+    background-color: var(--dark-blue-color) !important;
+    color: #fff !important;
+    border-radius: 30px !important;
+}
+
+button.copy-to-clipboard-button:hover {
+    background-color: var(--dark-magenta-color) !important;
+    border-color: var(--dark-magenta-color) !important;
+}
+
diff --git a/styles/prism.css b/styles/prism.css
new file mode 100644
index 0000000000..9d07cb7056
--- /dev/null
+++ b/styles/prism.css
@@ -0,0 +1,5 @@
+/* PrismJS 1.30.0
+https://prismjs.com/download#themes=prism&languages=bash+powershell&plugins=line-numbers+show-language+remove-initial-line-feed+toolbar+copy-to-clipboard
 */
+code[class*=language-],pre[class*=language-]{color:#000;background:0 
0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu 
Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-]
 ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] 
::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-]
 ::selection,code[class*=language-]::selection,pre[class*=language-] 
::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media
 
print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em
 
0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css
 .token.string,.style 
.token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
+pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers
 
.line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px
 solid 
#999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}
+div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:.3em;right:.2em;transition:opacity
 .3s 
ease-in-out;opacity:0}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:0
 
0;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:.8em;padding:0
 .5em;background:#f5f2f0;background:rgba(224,224,224,.2);box-shadow:0 2px 0 0 
rgba(0,0,0,.2);border-radius:.5em}div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover{color:inherit;text-decoration:none}
\ No newline at end of file
diff --git a/styles/theme-base.css b/styles/theme-base.css
index c28b2a1385..59b4ad6329 100644
--- a/styles/theme-base.css
+++ b/styles/theme-base.css
@@ -508,6 +508,27 @@ div.classsynopsisinfo_comment {
     margin-top:1.5rem;
 }
 
+.instructions {
+    margin-bottom: 2rem;
+}
+
+.instructions p {
+    margin: 1rem 0;
+}
+
+.instructions-form {
+    display: flex;
+    flex-direction: column;
+    gap: .75rem;
+    margin-bottom: 2rem;
+}
+
+.instructions-label {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+}
+
 .warn {
     padding: .75rem 1rem;
     margin: 1.5rem 0 1.5rem 1.5rem;

Reply via email to