From 4473f1b924ec4e9296dba7996a6ee71ea4efb0eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 9 Dec 2024 22:45:24 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20KMJ-007/?= =?UTF-8?q?lazygh@a9f6c43890bee2edf7da6f80c3f00c00f9e27bad=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- artifacts.js | 245 +++++++ artifacts.json | 1 + artifacts/index.html | 360 +++++++++++ changelog.rss | 1 + changelog/index.html | 189 ++++++ changelog/v0.1.0/index.html | 125 ++++ changelog/v0.5.0/index.html | 125 ++++ favicon.ico | 20 + index.html | 796 +++++++++++++++++++++++ lazygh-installer.ps1.txt | 465 ++++++++++++++ lazygh-installer.sh.txt | 1196 +++++++++++++++++++++++++++++++++++ oranda-v0.6.1.css | 3 + 12 files changed, 3526 insertions(+) create mode 100644 artifacts.js create mode 100644 artifacts.json create mode 100644 artifacts/index.html create mode 100644 changelog.rss create mode 100644 changelog/index.html create mode 100644 changelog/v0.1.0/index.html create mode 100644 changelog/v0.5.0/index.html create mode 100644 favicon.ico create mode 100644 index.html create mode 100644 lazygh-installer.ps1.txt create mode 100644 lazygh-installer.sh.txt create mode 100644 oranda-v0.6.1.css diff --git a/artifacts.js b/artifacts.js new file mode 100644 index 0000000..2dbfc70 --- /dev/null +++ b/artifacts.js @@ -0,0 +1,245 @@ +/* Code modified from the blender website + * https://www.blender.org/wp-content/themes/bthree/assets/js/get_os.js?x82196 + */ + +let options = { + windows64: "x86_64-pc-windows", + windows32: "i686-pc-windows", + windowsArm: "aarch64-pc-windows", + + mac64: "x86_64-apple", + mac32: "i686-apple", + macSilicon: "aarch64-apple", + + linux64: "x86_64-unknown-linux", + linux32: "i686-unknown-linux", + linuxArm: "aarch64-unknown-linux", + + // ios: "ios", + // android: "linux-android", + // freebsd: "freebsd", +}; + +function isAppleSilicon() { + try { + var glcontext = document.createElement("canvas").getContext("webgl"); + var debugrenderer = glcontext + ? glcontext.getExtension("WEBGL_debug_renderer_info") + : null; + var renderername = + (debugrenderer && + glcontext.getParameter(debugrenderer.UNMASKED_RENDERER_WEBGL)) || + ""; + if (renderername.match(/Apple M/) || renderername.match(/Apple GPU/)) { + return true; + } + + return false; + } catch (e) {} +} + +function getOS() { + var OS = options.windows64.default; + var userAgent = navigator.userAgent; + var platform = navigator.platform; + + if (navigator.appVersion.includes("Win")) { + if ( + !userAgent.includes("Windows NT 5.0") && + !userAgent.includes("Windows NT 5.1") && + (userAgent.indexOf("Win64") > -1 || + platform == "Win64" || + userAgent.indexOf("x86_64") > -1 || + userAgent.indexOf("x86_64") > -1 || + userAgent.indexOf("amd64") > -1 || + userAgent.indexOf("AMD64") > -1 || + userAgent.indexOf("WOW64") > -1) + ) { + OS = options.windows64; + } else { + if ( + window.external && + window.external.getHostEnvironmentValue && + window.external + .getHostEnvironmentValue("os-architecture") + .includes("ARM64") + ) { + OS = options.windowsArm; + } else { + try { + var canvas = document.createElement("canvas"); + var gl = canvas.getContext("webgl"); + + var debugInfo = gl.getExtension("WEBGL_debug_renderer_info"); + var renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL); + if (renderer.includes("Qualcomm")) OS = options.windowsArm; + } catch (e) {} + } + } + } + + //MacOS, MacOS X, macOS + if (navigator.appVersion.includes("Mac")) { + if ( + navigator.userAgent.includes("OS X 10.5") || + navigator.userAgent.includes("OS X 10.6") + ) { + OS = options.mac32; + } else { + OS = options.mac64; + + const isSilicon = isAppleSilicon(); + if (isSilicon) { + OS = options.macSilicon; + } + } + } + + // linux + if (platform.includes("Linux")) { + OS = options.linux64; + // FIXME: Can we find out whether linux 32-bit or ARM are used? + } + + // if ( + // userAgent.includes("iPad") || + // userAgent.includes("iPhone") || + // userAgent.includes("iPod") + // ) { + // OS = options.ios; + // } + // if (platform.toLocaleLowerCase().includes("freebsd")) { + // OS = options.freebsd; + // } + + return OS; +} + +let os = getOS(); +window.os = os; + +// Unhide and hydrate selector with events +const archSelect = document.querySelector(".arch-select"); +if (archSelect) { + archSelect.classList.remove("hidden"); + const selector = document.querySelector("#install-arch-select"); + if (selector) { + selector.addEventListener("change", onArchChange); + } +} + +// Hydrate tab buttons with events +Array.from(document.querySelectorAll(".install-tab[data-id]")).forEach((tab) => { + tab.addEventListener("click", onTabClick); +}); + +function onArchChange(evt) { + // Get target + const target = evt.currentTarget.value; + // Find corresponding installer lists + const newContentEl = document.querySelector(`.arch[data-arch=${target}]`); + const oldContentEl = document.querySelector(`.arch[data-arch]:not(.hidden)`); + // Hide old content element (if applicable) + if (oldContentEl) { + oldContentEl.classList.add("hidden"); + } + // Show new content element + newContentEl.classList.remove("hidden"); + // Show the first tab's content if nothing was selected before + if (newContentEl.querySelectorAll(".install-tab.selected").length === 0) { + const firstContentChild = newContentEl.querySelector(".install-content:first-of-type"); + const firstTabChild = newContentEl.querySelector(".install-tab:first-of-type"); + firstContentChild.classList.remove("hidden"); + if (firstTabChild) { + firstTabChild.classList.add("selected"); + } + } + // Hide "no OS detected" message + const noDetectEl = document.querySelector(".no-autodetect"); + noDetectEl.classList.add("hidden"); + // Hide Mac hint + document.querySelector(".mac-switch").classList.add("hidden"); +} + +function onTabClick(evt) { + // Get target and ID + const {triple, id} = evt.currentTarget.dataset; + if (triple) { + // Find corresponding content elements + const newContentEl = document.querySelector(`.install-content[data-id="${String(id)}"][data-triple=${triple}]`); + const oldContentEl = document.querySelector(`.install-content[data-triple=${triple}][data-id]:not(.hidden)`); + // Find old tab to unselect + const oldTabEl = document.querySelector(`.install-tab[data-triple=${triple}].selected`); + // Hide old content element + if (oldContentEl && oldTabEl) { + oldContentEl.classList.add("hidden"); + oldTabEl.classList.remove("selected"); + } + + // Unhide new content element + newContentEl.classList.remove("hidden"); + // Select new tab element + evt.currentTarget.classList.add("selected"); + } +} + +const allPlatforms = Array.from(document.querySelectorAll(`.arch[data-arch]`)); +let hit = allPlatforms.find( + (a) => { + // Show Intel Mac downloads if no M1 Mac downloads are available + if ( + a.attributes["data-arch"].value.includes(options.mac64) && + os.includes(options.macSilicon) && + !allPlatforms.find(p => p.attributes["data-arch"].value.includes(options.macSilicon))) { + // Unhide hint + document.querySelector(".mac-switch").classList.remove("hidden"); + return true; + } + return a.attributes["data-arch"].value.includes(os); + } +); + +if (hit) { + hit.classList.remove("hidden"); + const selectEl = document.querySelector("#install-arch-select"); + selectEl.value = hit.dataset.arch; + const firstContentChild = hit.querySelector(".install-content:first-of-type"); + const firstTabChild = hit.querySelector(".install-tab:first-of-type"); + firstContentChild.classList.remove("hidden"); + if (firstTabChild) { + firstTabChild.classList.add("selected"); + } +} else { + const noDetectEl = document.querySelector(".no-autodetect"); + if (noDetectEl) { + const noDetectElDetails = document.querySelector(".no-autodetect-details"); + if (noDetectElDetails) { + noDetectElDetails.innerHTML = `We detected you're on ${os} but there don't seem to be installers for that. ` + } + noDetectEl.classList.remove("hidden"); + } +} + +let copyButtons = Array.from(document.querySelectorAll("[data-copy]")); +if (copyButtons.length) { + copyButtons.forEach(function (element) { + element.addEventListener("click", () => { + navigator.clipboard.writeText(element.attributes["data-copy"].value); + }); + }); +} + +// Toggle for pre releases +const checkbox = document.getElementById("show-prereleases"); + +if (checkbox) { + checkbox.addEventListener("click", () => { + const all = document.getElementsByClassName("pre-release"); + + if (all) { + for (var item of all) { + item.classList.toggle("hidden"); + } + } + }); +} \ No newline at end of file diff --git a/artifacts.json b/artifacts.json new file mode 100644 index 0000000..0056402 --- /dev/null +++ b/artifacts.json @@ -0,0 +1 @@ +{"format_version":"0.6.1","tag":"v0.5.0","formatted_date":"Sep 16 2024 at 06:35 UTC","platforms_with_downloads":[{"target":["aarch64-apple-darwin"],"display_name":"macOS Apple Silicon","installers":[11,8,1,2]},{"target":["x86_64-apple-darwin"],"display_name":"macOS Intel","installers":[11,8,1,3]},{"target":["x86_64-pc-windows-msvc"],"display_name":"Windows x64","installers":[10,8,5,4]},{"target":["x86_64-unknown-linux-gnu"],"display_name":"Linux x64","installers":[11,8,1,6]},{"target":["x86_64-unknown-linux-musl"],"display_name":"musl Linux x64","installers":[11,8,7]}],"downloadable_files":[[2,{"name":"lazygh-aarch64-apple-darwin.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-aarch64-apple-darwin.tar.gz","view_path":null,"checksum_file":3},["macOS Apple Silicon"]],[8,{"name":"lazygh-x86_64-apple-darwin.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-apple-darwin.tar.gz","view_path":null,"checksum_file":9},["macOS Intel"]],[11,{"name":"lazygh-x86_64-pc-windows-msvc.msi","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-pc-windows-msvc.msi","view_path":null,"checksum_file":12},["Windows x64"]],[13,{"name":"lazygh-x86_64-pc-windows-msvc.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-pc-windows-msvc.tar.gz","view_path":null,"checksum_file":14},["Windows x64"]],[16,{"name":"lazygh-x86_64-unknown-linux-gnu.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-unknown-linux-gnu.tar.gz","view_path":null,"checksum_file":17},["Linux x64"]],[19,{"name":"lazygh-x86_64-unknown-linux-musl.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-unknown-linux-musl.tar.gz","view_path":null,"checksum_file":20},["musl Linux x64"]]],"release":{"artifacts":{"files":[{"name":"dist-manifest.json","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/dist-manifest.json","view_path":null,"checksum_file":null},{"name":"lazygh-aarch64-apple-darwin-update","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-aarch64-apple-darwin-update","view_path":null,"checksum_file":null},{"name":"lazygh-aarch64-apple-darwin.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-aarch64-apple-darwin.tar.gz","view_path":null,"checksum_file":3},{"name":"lazygh-aarch64-apple-darwin.tar.gz.sha256","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-aarch64-apple-darwin.tar.gz.sha256","view_path":null,"checksum_file":null},{"name":"lazygh-installer.ps1","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-installer.ps1","view_path":"lazygh-installer.ps1.txt","checksum_file":null},{"name":"lazygh-installer.sh","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-installer.sh","view_path":"lazygh-installer.sh.txt","checksum_file":null},{"name":"lazygh-npm-package.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-npm-package.tar.gz","view_path":null,"checksum_file":null},{"name":"lazygh-x86_64-apple-darwin-update","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-apple-darwin-update","view_path":null,"checksum_file":null},{"name":"lazygh-x86_64-apple-darwin.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-apple-darwin.tar.gz","view_path":null,"checksum_file":9},{"name":"lazygh-x86_64-apple-darwin.tar.gz.sha256","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-apple-darwin.tar.gz.sha256","view_path":null,"checksum_file":null},{"name":"lazygh-x86_64-pc-windows-msvc-update","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-pc-windows-msvc-update","view_path":null,"checksum_file":null},{"name":"lazygh-x86_64-pc-windows-msvc.msi","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-pc-windows-msvc.msi","view_path":null,"checksum_file":12},{"name":"lazygh-x86_64-pc-windows-msvc.msi.sha256","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-pc-windows-msvc.msi.sha256","view_path":null,"checksum_file":null},{"name":"lazygh-x86_64-pc-windows-msvc.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-pc-windows-msvc.tar.gz","view_path":null,"checksum_file":14},{"name":"lazygh-x86_64-pc-windows-msvc.tar.gz.sha256","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-pc-windows-msvc.tar.gz.sha256","view_path":null,"checksum_file":null},{"name":"lazygh-x86_64-unknown-linux-gnu-update","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-unknown-linux-gnu-update","view_path":null,"checksum_file":null},{"name":"lazygh-x86_64-unknown-linux-gnu.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-unknown-linux-gnu.tar.gz","view_path":null,"checksum_file":17},{"name":"lazygh-x86_64-unknown-linux-gnu.tar.gz.sha256","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-unknown-linux-gnu.tar.gz.sha256","view_path":null,"checksum_file":null},{"name":"lazygh-x86_64-unknown-linux-musl-update","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-unknown-linux-musl-update","view_path":null,"checksum_file":null},{"name":"lazygh-x86_64-unknown-linux-musl.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-unknown-linux-musl.tar.gz","view_path":null,"checksum_file":20},{"name":"lazygh-x86_64-unknown-linux-musl.tar.gz.sha256","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-x86_64-unknown-linux-musl.tar.gz.sha256","view_path":null,"checksum_file":null},{"name":"lazygh.rb","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh.rb","view_path":null,"checksum_file":null},{"name":"source.tar.gz","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/source.tar.gz","view_path":null,"checksum_file":23},{"name":"source.tar.gz.sha256","download_url":"https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/source.tar.gz.sha256","view_path":null,"checksum_file":null}],"installers":[{"label":"npm","description":"Install prebuilt binaries into your npm project","app_name":null,"method":{"type":"Run","file":null,"run_hint":"npm install lazygh@0.5.0"}},{"label":"homebrew","description":"Install prebuilt binaries via Homebrew","app_name":null,"method":{"type":"Run","file":null,"run_hint":"brew install kmj-007/lazygh/lazygh"}},{"label":"tarball","description":"","app_name":null,"method":{"type":"Download","file":2}},{"label":"tarball","description":"","app_name":null,"method":{"type":"Download","file":8}},{"label":"tarball","description":"","app_name":null,"method":{"type":"Download","file":13}},{"label":"msi","description":"install via msi","app_name":null,"method":{"type":"Download","file":11}},{"label":"tarball","description":"","app_name":null,"method":{"type":"Download","file":16}},{"label":"tarball","description":"","app_name":null,"method":{"type":"Download","file":19}},{"label":"cargo","description":"","app_name":null,"method":{"type":"Run","file":null,"run_hint":"cargo install lazygh"}},{"label":"npx","description":"","app_name":null,"method":{"type":"Run","file":null,"run_hint":"npx lazygh"}},{"label":"powershell","description":"","app_name":null,"method":{"type":"Run","file":4,"run_hint":"irm https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-installer.ps1 | iex"}},{"label":"shell","description":"","app_name":null,"method":{"type":"Run","file":5,"run_hint":"curl --proto '=https' --tlsv1.2 -LsSf https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-installer.sh | sh"}}],"targets":{"aarch64-apple-darwin":[11,8,1,2],"aarch64-pc-windows-msvc":[10,8],"aarch64-unknown-linux-gnu":[11,8],"aarch64-unknown-linux-musl":[11,8],"i686-apple-darwin":[11,8],"i686-pc-windows-msvc":[10,8],"i686-unknown-linux-gnu":[11,8],"i686-unknown-linux-musl":[11,8],"x86_64-apple-darwin":[11,8,1,3],"x86_64-pc-windows-msvc":[10,8,5,4],"x86_64-unknown-linux-gnu":[11,8,1,6],"x86_64-unknown-linux-musl":[11,8,7]}}},"os_script":"/lazygh/artifacts.js","has_checksum_files":true} \ No newline at end of file diff --git a/artifacts/index.html b/artifacts/index.html new file mode 100644 index 0000000..fc21d6b --- /dev/null +++ b/artifacts/index.html @@ -0,0 +1,360 @@ + + + + lazygh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ +

lazygh

+ + + +
+ + +
+
+ + + +
+

cargo

+
+
+cargo install lazygh
+ + + + +
+
+ + + + +
+

homebrew

+
+
+brew install kmj-007/lazygh/lazygh
+ + + + +
+
+ + + + + + +
+

npm

+
+
+npm install lazygh@0.5.0
+ + + + +
+
+ + + + +
+

npx

+
+
+npx lazygh
+ + + + +
+
+ + + + +
+

powershell

+
+
+irm https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-installer.ps1 | iex
+ + + + + + + + + Source + +
+
+ + + + +
+

shell

+
+
+curl --proto '=https' --tlsv1.2 -LsSf https://github.com/KMJ-007/lazygh/releases/download/v0.5.0/lazygh-installer.sh | sh
+ + + + + + + + + Source + +
+
+ + + + + + + + + + + + +
+
+

Downloads

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FilePlatformChecksum
lazygh-aarch64-apple-darwin.tar.gz + + + macOS Apple Silicon + + + checksum
lazygh-x86_64-apple-darwin.tar.gz + + + macOS Intel + + + checksum
lazygh-x86_64-pc-windows-msvc.msi + + + Windows x64 + + + checksum
lazygh-x86_64-pc-windows-msvc.tar.gz + + + Windows x64 + + + checksum
lazygh-x86_64-unknown-linux-gnu.tar.gz + + + Linux x64 + + + checksum
lazygh-x86_64-unknown-linux-musl.tar.gz + + + musl Linux x64 + + + checksum
+
+
+ +
+
+ +
+ + + + + lazygh, MIT + +
+
+ + + + + + window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());gtag('config', 'G-TKS59X89PP'); + + + + + + + \ No newline at end of file diff --git a/changelog.rss b/changelog.rss new file mode 100644 index 0000000..a4309cb --- /dev/null +++ b/changelog.rss @@ -0,0 +1 @@ +lazygh Changeloghttp://127.0.0.1:7979/lazygh/changelogChangelog information for lazyghlazygh Changelogv0.5.0http://127.0.0.1:7979/lazygh/changelog/v0.5.0lazygh Changeloghttp://127.0.0.1:7979/lazygh/changelog/v0.5.0v0.1.0http://127.0.0.1:7979/lazygh/changelog/v0.1.0lazygh Changeloghttp://127.0.0.1:7979/lazygh/changelog/v0.1.0 \ No newline at end of file diff --git a/changelog/index.html b/changelog/index.html new file mode 100644 index 0000000..2f2cdc9 --- /dev/null +++ b/changelog/index.html @@ -0,0 +1,189 @@ + + + + lazygh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ +

lazygh

+ + + +
+ + +
+

+ Releases + + + + + + +

+
+ + +
+ + +
+

+ + + v0.5.0 + + +

+
+ + + + + v0.5.0 + + + + + Sep 16 2024 at 06:35 UTC + + +
+
+ +
+
+ + +
+

+ + + v0.1.0 + + +

+
+ + + + + v0.1.0 + + + + + Sep 16 2024 at 04:27 UTC + + +
+
+ +
+
+ +
+
+
+ +
+
+ +
+ + + + + lazygh, MIT + +
+
+ + + + + + window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());gtag('config', 'G-TKS59X89PP'); + + + + + + + \ No newline at end of file diff --git a/changelog/v0.1.0/index.html b/changelog/v0.1.0/index.html new file mode 100644 index 0000000..4cd47ce --- /dev/null +++ b/changelog/v0.1.0/index.html @@ -0,0 +1,125 @@ + + + + lazygh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ +

lazygh

+ + + +
+ + +
+

v0.1.0

+
+ + +
+ +
+ + + + + v0.1.0 + + + + + Sep 16 2024 at 04:27 UTC + + +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + lazygh, MIT + +
+
+ + + + + + window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());gtag('config', 'G-TKS59X89PP'); + + + + + \ No newline at end of file diff --git a/changelog/v0.5.0/index.html b/changelog/v0.5.0/index.html new file mode 100644 index 0000000..d0ac5b6 --- /dev/null +++ b/changelog/v0.5.0/index.html @@ -0,0 +1,125 @@ + + + + lazygh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ +

lazygh

+ + + +
+ + +
+

v0.5.0

+
+ + +
+ +
+ + + + + v0.5.0 + + + + + Sep 16 2024 at 06:35 UTC + + +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + lazygh, MIT + +
+
+ + + + + + window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());gtag('config', 'G-TKS59X89PP'); + + + + + \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..4317850 --- /dev/null +++ b/favicon.ico @@ -0,0 +1,20 @@ + >o_o< axodotdev - 404
404 Not Found

404 Not Found

Whoops! That page doesn't exist.

\ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..d6cb2a7 --- /dev/null +++ b/index.html @@ -0,0 +1,796 @@ + + + + lazygh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ +

lazygh

+ + + +
+ + + + + + + +
+
+

Install v0.5.0

+ +
Published on Sep 16 2024 at 06:35 UTC
+ + +
    + + + + + + + + + + + +
+
+ + + + + + + + + +
+ View all installation options + + + +
+
+ +View all installation options + + +

LazyGH

+

⚠️ WARNING: This project is highly under development. Do not use in production. There are several security issues which are yet to be addressed. ⚠️

+

LazyGH is a Terminal User Interface (TUI) application for managing multiple GitHub accounts easily. It allows you to switch between different Git configurations and SSH keys seamlessly.

+

Demo

+

Check out the demo to see LazyGH in action:

+

LazyGH Demo

+

Features

+
    +
  • Manage multiple GitHub accounts
  • +
  • Switch between accounts with ease
  • +
  • Automatically update Git global configuration
  • +
  • Generate and manage SSH keys for each account
  • +
  • Copy SSH public keys to clipboard
  • +
+

Contributing

+

Contributions are welcome! Here's how you can contribute:

+
    +
  1. Fork the repository
  2. +
  3. Create your feature branch (git checkout -b feature/AmazingFeature)
  4. +
  5. Commit your changes (git commit -m 'Add some AmazingFeature')
  6. +
  7. Push to the branch (git push origin feature/AmazingFeature)
  8. +
  9. Open a Pull Request
  10. +
+

Please make sure to update tests as appropriate and adhere to the existing coding style.

+

Issues

+

If you encounter any problems or have suggestions for improvements, please open an issue on the GitHub Issues page.

+

Roadmap

+
    +
  • fix the cargo auto release version mangment with release workflow
  • +
  • adding lazygh to binstall
  • +
  • adding lazygh to nix-env
  • +
  • adding lazygh to nix flake
  • +
  • ability to maintain multiple gh config files and able to categorise them in workspace fashion but in simpler way
  • +
  • don't know other things to add, create an issue if you have any ideas
  • +
+

Security

+

LazyGH takes your security seriously. If you discover a security vulnerability within LazyGH, please send an e-mail to Karan Janthe via karanjanthe@gmail.com. All security vulnerabilities will be addressed.

+

Acknowledgements

+
    +
  • Ratatui for the excellent TUI framework
  • +
  • Tweet for the idea and inspiration
  • +
  • All the contributors who have helped shape LazyGH
  • +
+

Contact

+

Karan Janthe - @KaranJanthe

+

Project Link: https://github.com/KMJ-007/lazygh

+ + + +
+
+ +
+ + + + + lazygh, MIT + +
+
+ + + + + + window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());gtag('config', 'G-TKS59X89PP'); + + + + + + + + + \ No newline at end of file diff --git a/lazygh-installer.ps1.txt b/lazygh-installer.ps1.txt new file mode 100644 index 0000000..421b61a --- /dev/null +++ b/lazygh-installer.ps1.txt @@ -0,0 +1,465 @@ +# Licensed under the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +<# +.SYNOPSIS + +The installer for lazygh 0.5.0 + +.DESCRIPTION + +This script detects what platform you're on and fetches an appropriate archive from +https://github.com/kmj-007/lazygh/releases/download/v0.5.0 +then unpacks the binaries and installs them to + + $env:CARGO_HOME/bin (or $HOME/.cargo/bin) + +It will then add that dir to PATH by editing your Environment.Path registry key + +.PARAMETER ArtifactDownloadUrl +The URL of the directory where artifacts can be fetched from + +.PARAMETER NoModifyPath +Don't add the install directory to PATH + +.PARAMETER Help +Print help + +#> + +param ( + [Parameter(HelpMessage = "The URL of the directory where artifacts can be fetched from")] + [string]$ArtifactDownloadUrl = 'https://github.com/kmj-007/lazygh/releases/download/v0.5.0', + [Parameter(HelpMessage = "Don't add the install directory to PATH")] + [switch]$NoModifyPath, + [Parameter(HelpMessage = "Print Help")] + [switch]$Help +) + +$app_name = 'lazygh' +$app_version = '0.5.0' + +$receipt = @" +{"binaries":["CARGO_DIST_BINS"],"binary_aliases":{},"cdylibs":["CARGO_DIST_DYLIBS"],"cstaticlibs":["CARGO_DIST_STATICLIBS"],"install_prefix":"AXO_INSTALL_PREFIX","provider":{"source":"cargo-dist","version":"0.22.1"},"source":{"app_name":"lazygh","name":"lazygh","owner":"kmj-007","release_type":"github"},"version":"0.5.0"} +"@ +$receipt_home = "${env:LOCALAPPDATA}\lazygh" + +function Install-Binary($install_args) { + if ($Help) { + Get-Help $PSCommandPath -Detailed + Exit + } + + Initialize-Environment + + # Platform info injected by cargo-dist + $platforms = @{ + "aarch64-pc-windows-msvc" = @{ + "artifact_name" = "lazygh-x86_64-pc-windows-msvc.tar.gz" + "bins" = @("lazygh.exe") + "libs" = @() + "staticlibs" = @() + "zip_ext" = ".tar.gz" + "aliases" = @{ + } + "aliases_json" = '{}' + "updater" = @{ + "artifact_name" = "lazygh-x86_64-pc-windows-msvc-update" + "bin" = "lazygh-x86_64-pc-windows-msvc-update" + } + } + "x86_64-pc-windows-msvc" = @{ + "artifact_name" = "lazygh-x86_64-pc-windows-msvc.tar.gz" + "bins" = @("lazygh.exe") + "libs" = @() + "staticlibs" = @() + "zip_ext" = ".tar.gz" + "aliases" = @{ + } + "aliases_json" = '{}' + "updater" = @{ + "artifact_name" = "lazygh-x86_64-pc-windows-msvc-update" + "bin" = "lazygh-x86_64-pc-windows-msvc-update" + } + } + } + + $fetched = Download "$ArtifactDownloadUrl" $platforms + # FIXME: add a flag that lets the user not do this step + try { + Invoke-Installer -artifacts $fetched -platforms $platforms "$install_args" + } catch { + throw @" +We encountered an error trying to perform the installation; +please review the error messages below. + +$_ +"@ + } +} + +function Get-TargetTriple() { + try { + # NOTE: this might return X64 on ARM64 Windows, which is OK since emulation is available. + # It works correctly starting in PowerShell Core 7.3 and Windows PowerShell in Win 11 22H2. + # Ideally this would just be + # [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture + # but that gets a type from the wrong assembly on Windows PowerShell (i.e. not Core) + $a = [System.Reflection.Assembly]::LoadWithPartialName("System.Runtime.InteropServices.RuntimeInformation") + $t = $a.GetType("System.Runtime.InteropServices.RuntimeInformation") + $p = $t.GetProperty("OSArchitecture") + # Possible OSArchitecture Values: https://learn.microsoft.com/dotnet/api/system.runtime.interopservices.architecture + # Rust supported platforms: https://doc.rust-lang.org/stable/rustc/platform-support.html + switch ($p.GetValue($null).ToString()) + { + "X86" { return "i686-pc-windows-msvc" } + "X64" { return "x86_64-pc-windows-msvc" } + "Arm" { return "thumbv7a-pc-windows-msvc" } + "Arm64" { return "aarch64-pc-windows-msvc" } + } + } catch { + # The above was added in .NET 4.7.1, so Windows PowerShell in versions of Windows + # prior to Windows 10 v1709 may not have this API. + Write-Verbose "Get-TargetTriple: Exception when trying to determine OS architecture." + Write-Verbose $_ + } + + # This is available in .NET 4.0. We already checked for PS 5, which requires .NET 4.5. + Write-Verbose("Get-TargetTriple: falling back to Is64BitOperatingSystem.") + if ([System.Environment]::Is64BitOperatingSystem) { + return "x86_64-pc-windows-msvc" + } else { + return "i686-pc-windows-msvc" + } +} + +function Download($download_url, $platforms) { + $arch = Get-TargetTriple + + if (-not $platforms.ContainsKey($arch)) { + $platforms_json = ConvertTo-Json $platforms + throw "ERROR: could not find binaries for this platform. Last platform tried: $arch platform info: $platforms_json" + } + + # Lookup what we expect this platform to look like + $info = $platforms[$arch] + $zip_ext = $info["zip_ext"] + $bin_names = $info["bins"] + $lib_names = $info["libs"] + $staticlib_names = $info["staticlibs"] + $artifact_name = $info["artifact_name"] + + # Make a new temp dir to unpack things to + $tmp = New-Temp-Dir + $dir_path = "$tmp\$app_name$zip_ext" + + # Download and unpack! + $url = "$download_url/$artifact_name" + Write-Information "Downloading $app_name $app_version ($arch)" + Write-Verbose " from $url" + Write-Verbose " to $dir_path" + $wc = New-Object Net.Webclient + $wc.downloadFile($url, $dir_path) + + Write-Verbose "Unpacking to $tmp" + + # Select the tool to unpack the files with. + # + # As of windows 10(?), powershell comes with tar preinstalled, but in practice + # it only seems to support .tar.gz, and not xz/zstd. Still, we should try to + # forward all tars to it in case the user has a machine that can handle it! + switch -Wildcard ($zip_ext) { + ".zip" { + Expand-Archive -Path $dir_path -DestinationPath "$tmp"; + Break + } + ".tar.*" { + tar xf $dir_path --strip-components 1 -C "$tmp"; + Break + } + Default { + throw "ERROR: unknown archive format $zip_ext" + } + } + + # Let the next step know what to copy + $bin_paths = @() + foreach ($bin_name in $bin_names) { + Write-Verbose " Unpacked $bin_name" + $bin_paths += "$tmp\$bin_name" + } + $lib_paths = @() + foreach ($lib_name in $lib_names) { + Write-Verbose " Unpacked $lib_name" + $lib_paths += "$tmp\$lib_name" + } + $staticlib_paths = @() + foreach ($lib_name in $staticlib_names) { + Write-Verbose " Unpacked $lib_name" + $staticlib_paths += "$tmp\$lib_name" + } + + if ($null -ne $info["updater"]) { + $updater_id = $info["updater"]["artifact_name"] + $updater_url = "$download_url/$updater_id" + $out_name = "$tmp\lazygh-update.exe" + + $wc.downloadFile($updater_url, $out_name) + $bin_paths += $out_name + } + + return @{ + "bin_paths" = $bin_paths + "lib_paths" = $lib_paths + "staticlib_paths" = $staticlib_paths + } +} + +function Invoke-Installer($artifacts, $platforms) { + # Replaces the placeholder binary entry with the actual list of binaries + $arch = Get-TargetTriple + + if (-not $platforms.ContainsKey($arch)) { + $platforms_json = ConvertTo-Json $platforms + throw "ERROR: could not find binaries for this platform. Last platform tried: $arch platform info: $platforms_json" + } + + $info = $platforms[$arch] + + # Forces the install to occur at this path, not the default + $force_install_dir = $null + # Check the newer app-specific variable before falling back + # to the older generic one + if (($env:LAZYGH_INSTALL_DIR)) { + $force_install_dir = $env:LAZYGH_INSTALL_DIR + } elseif (($env:CARGO_DIST_FORCE_INSTALL_DIR)) { + $force_install_dir = $env:CARGO_DIST_FORCE_INSTALL_DIR + } + + # The actual path we're going to install to + $dest_dir = $null + $dest_dir_lib = $null + # The install prefix we write to the receipt. + # For organized install methods like CargoHome, which have + # subdirectories, this is the root without `/bin`. For other + # methods, this is the same as `_install_dir`. + $receipt_dest_dir = $null + # Before actually consulting the configured install strategy, see + # if we're overriding it. + if (($force_install_dir)) { + + $dest_dir = Join-Path $force_install_dir "bin" + $dest_dir_lib = $dest_dir + $receipt_dest_dir = $force_install_dir + } + if (-Not $dest_dir) { + # first try $env:CARGO_HOME, then fallback to $HOME + # (for whatever reason $HOME is not a normal env var and doesn't need the $env: prefix) + $root = if (($base_dir = $env:CARGO_HOME)) { + $base_dir + } elseif (($base_dir = $HOME)) { + Join-Path $base_dir ".cargo" + } else { + throw "ERROR: could not find your HOME dir or CARGO_HOME to install binaries to" + } + + $dest_dir = Join-Path $root "bin" + $dest_dir_lib = $dest_dir + $receipt_dest_dir = $root + } + + # Looks like all of the above assignments failed + if (-Not $dest_dir) { + throw "ERROR: could not find a valid path to install to; please check the installation instructions" + } + + # The replace call here ensures proper escaping is inlined into the receipt + $receipt = $receipt.Replace('AXO_INSTALL_PREFIX', $receipt_dest_dir.replace("\", "\\")) + + $dest_dir = New-Item -Force -ItemType Directory -Path $dest_dir + $dest_dir_lib = New-Item -Force -ItemType Directory -Path $dest_dir_lib + Write-Information "Installing to $dest_dir" + # Just copy the binaries from the temp location to the install dir + foreach ($bin_path in $artifacts["bin_paths"]) { + $installed_file = Split-Path -Path "$bin_path" -Leaf + Copy-Item "$bin_path" -Destination "$dest_dir" -ErrorAction Stop + Remove-Item "$bin_path" -Recurse -Force -ErrorAction Stop + Write-Information " $installed_file" + + if (($dests = $info["aliases"][$installed_file])) { + $source = Join-Path "$dest_dir" "$installed_file" + foreach ($dest_name in $dests) { + $dest = Join-Path $dest_dir $dest_name + $null = New-Item -ItemType HardLink -Target "$source" -Path "$dest" -Force -ErrorAction Stop + } + } + } + foreach ($lib_path in $artifacts["lib_paths"]) { + $installed_file = Split-Path -Path "$lib_path" -Leaf + Copy-Item "$lib_path" -Destination "$dest_dir_lib" -ErrorAction Stop + Remove-Item "$lib_path" -Recurse -Force -ErrorAction Stop + Write-Information " $installed_file" + } + foreach ($lib_path in $artifacts["staticlib_paths"]) { + $installed_file = Split-Path -Path "$lib_path" -Leaf + Copy-Item "$lib_path" -Destination "$dest_dir_lib" -ErrorAction Stop + Remove-Item "$lib_path" -Recurse -Force -ErrorAction Stop + Write-Information " $installed_file" + } + + $formatted_bins = ($info["bins"] | ForEach-Object { '"' + $_ + '"' }) -join "," + $receipt = $receipt.Replace('"CARGO_DIST_BINS"', $formatted_bins) + $formatted_libs = ($info["libs"] | ForEach-Object { '"' + $_ + '"' }) -join "," + $receipt = $receipt.Replace('"CARGO_DIST_DYLIBS"', $formatted_libs) + $formatted_staticlibs = ($info["staticlibs"] | ForEach-Object { '"' + $_ + '"' }) -join "," + $receipt = $receipt.Replace('"CARGO_DIST_STATICLIBS"', $formatted_staticlibs) + # Also replace the aliases with the arch-specific one + $receipt = $receipt.Replace('"binary_aliases":{}', -join('"binary_aliases":', $info['aliases_json'])) + + # Write the install receipt + $null = New-Item -Path $receipt_home -ItemType "directory" -ErrorAction SilentlyContinue + # Trying to get Powershell 5.1 (not 6+, which is fake and lies) to write utf8 is a crime + # because "Out-File -Encoding utf8" actually still means utf8BOM, so we need to pull out + # .NET's APIs which actually do what you tell them (also apparently utf8NoBOM is the + # default in newer .NETs but I'd rather not rely on that at this point). + $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False + [IO.File]::WriteAllLines("$receipt_home/lazygh-receipt.json", "$receipt", $Utf8NoBomEncoding) + + # Respect the environment, but CLI takes precedence + if ($null -eq $NoModifyPath) { + $NoModifyPath = $env:INSTALLER_NO_MODIFY_PATH + } + + Write-Information "everything's installed!" + if (-not $NoModifyPath) { + Add-Ci-Path $dest_dir + if (Add-Path $dest_dir) { + Write-Information "" + Write-Information "To add $dest_dir to your PATH, either restart your system or run:" + Write-Information "" + Write-Information " set Path=$dest_dir;%Path% (cmd)" + Write-Information " `$env:Path = `"$dest_dir;`$env:Path`" (powershell)" + } + } +} + +# Attempt to do CI-specific rituals to get the install-dir on PATH faster +function Add-Ci-Path($OrigPathToAdd) { + # If GITHUB_PATH is present, then write install_dir to the file it refs. + # After each GitHub Action, the contents will be added to PATH. + # So if you put a curl | sh for this script in its own "run" step, + # the next step will have this dir on PATH. + # + # Note that GITHUB_PATH will not resolve any variables, so we in fact + # want to write the install dir and not an expression that evals to it + if (($gh_path = $env:GITHUB_PATH)) { + Write-Output "$OrigPathToAdd" | Out-File -FilePath "$gh_path" -Encoding utf8 -Append + } +} + +# Try to add the given path to PATH via the registry +# +# Returns true if the registry was modified, otherwise returns false +# (indicating it was already on PATH) +function Add-Path($OrigPathToAdd) { + Write-Verbose "Adding $OrigPathToAdd to your PATH" + $RegistryPath = "HKCU:\Environment" + $PropertyName = "Path" + $PathToAdd = $OrigPathToAdd + + $Item = if (Test-Path $RegistryPath) { + # If the registry key exists, get it + Get-Item -Path $RegistryPath + } else { + # If the registry key doesn't exist, create it + Write-Verbose "Creating $RegistryPath" + New-Item -Path $RegistryPath -Force + } + + $OldPath = "" + try { + # Try to get the old PATH value. If that fails, assume we're making it from scratch. + # Otherwise assume there's already paths in here and use a ; separator + $OldPath = $Item | Get-ItemPropertyValue -Name $PropertyName + $PathToAdd = "$PathToAdd;" + } catch { + # We'll be creating the PATH from scratch + Write-Verbose "No $PropertyName Property exists on $RegistryPath (we'll make one)" + } + + # Check if the path is already there + # + # We don't want to incorrectly match "C:\blah\" to "C:\blah\blah\", so we include the semicolon + # delimiters when searching, ensuring exact matches. To avoid corner cases we add semicolons to + # both sides of the input, allowing us to pretend we're always in the middle of a list. + Write-Verbose "Old $PropertyName Property is $OldPath" + if (";$OldPath;" -like "*;$OrigPathToAdd;*") { + # Already on path, nothing to do + Write-Verbose "install dir already on PATH, all done!" + return $false + } else { + # Actually update PATH + Write-Verbose "Actually mutating $PropertyName Property" + $NewPath = $PathToAdd + $OldPath + # We use -Force here to make the value already existing not be an error + $Item | New-ItemProperty -Name $PropertyName -Value $NewPath -PropertyType String -Force | Out-Null + return $true + } +} + +function Initialize-Environment() { + If (($PSVersionTable.PSVersion.Major) -lt 5) { + throw @" +Error: PowerShell 5 or later is required to install $app_name. +Upgrade PowerShell: + + https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell + +"@ + } + + # show notification to change execution policy: + $allowedExecutionPolicy = @('Unrestricted', 'RemoteSigned', 'ByPass') + If ((Get-ExecutionPolicy).ToString() -notin $allowedExecutionPolicy) { + throw @" +Error: PowerShell requires an execution policy in [$($allowedExecutionPolicy -join ", ")] to run $app_name. For example, to set the execution policy to 'RemoteSigned' please run: + + Set-ExecutionPolicy RemoteSigned -scope CurrentUser + +"@ + } + + # GitHub requires TLS 1.2 + If ([System.Enum]::GetNames([System.Net.SecurityProtocolType]) -notcontains 'Tls12') { + throw @" +Error: Installing $app_name requires at least .NET Framework 4.5 +Please download and install it first: + + https://www.microsoft.com/net/download + +"@ + } +} + +function New-Temp-Dir() { + [CmdletBinding(SupportsShouldProcess)] + param() + $parent = [System.IO.Path]::GetTempPath() + [string] $name = [System.Guid]::NewGuid() + New-Item -ItemType Directory -Path (Join-Path $parent $name) +} + +# PSScriptAnalyzer doesn't like how we use our params as globals, this calms it +$Null = $ArtifactDownloadUrl, $NoModifyPath, $Help +# Make Write-Information statements be visible +$InformationPreference = "Continue" + +# The default interactive handler +try { + Install-Binary "$Args" +} catch { + Write-Information $_ + exit 1 +} diff --git a/lazygh-installer.sh.txt b/lazygh-installer.sh.txt new file mode 100644 index 0000000..478e30d --- /dev/null +++ b/lazygh-installer.sh.txt @@ -0,0 +1,1196 @@ +#!/bin/sh +# shellcheck shell=dash +# +# Licensed under the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +if [ "$KSH_VERSION" = 'Version JM 93t+ 2010-03-05' ]; then + # The version of ksh93 that ships with many illumos systems does not + # support the "local" extension. Print a message rather than fail in + # subtle ways later on: + echo 'this installer does not work with this ksh93 version; please try bash!' >&2 + exit 1 +fi + +set -u + +APP_NAME="lazygh" +APP_VERSION="0.5.0" +ARTIFACT_DOWNLOAD_URL="${INSTALLER_DOWNLOAD_URL:-https://github.com/kmj-007/lazygh/releases/download/v0.5.0}" +PRINT_VERBOSE=${INSTALLER_PRINT_VERBOSE:-0} +PRINT_QUIET=${INSTALLER_PRINT_QUIET:-0} +NO_MODIFY_PATH=${INSTALLER_NO_MODIFY_PATH:-0} +read -r RECEIPT <&2 + say_verbose " from $_url" 1>&2 + say_verbose " to $_file" 1>&2 + + ensure mkdir -p "$_dir" + + if ! downloader "$_url" "$_file"; then + say "failed to download $_url" + say "this may be a standard network error, but it may also indicate" + say "that $APP_NAME's release process is not working. When in doubt" + say "please feel free to open an issue!" + exit 1 + fi + + # ...and then the updater, if it exists + if [ -n "$_updater_name" ]; then + local _updater_url="$ARTIFACT_DOWNLOAD_URL/$_updater_name" + # This renames the artifact while doing the download, removing the + # target triple and leaving just the appname-update format + local _updater_file="$_dir/$APP_NAME-update" + + if ! downloader "$_updater_url" "$_updater_file"; then + say "failed to download $_updater_url" + say "this may be a standard network error, but it may also indicate" + say "that $APP_NAME's release process is not working. When in doubt" + say "please feel free to open an issue!" + exit 1 + fi + + # Add the updater to the list of binaries to install + _bins="$_bins $APP_NAME-update" + fi + + # unpack the archive + case "$_zip_ext" in + ".zip") + ensure unzip -q "$_file" -d "$_dir" + ;; + + ".tar."*) + ensure tar xf "$_file" --strip-components 1 -C "$_dir" + ;; + *) + err "unknown archive format: $_zip_ext" + ;; + esac + + install "$_dir" "$_bins" "$_libs" "$_staticlibs" "$_arch" "$@" + local _retval=$? + if [ "$_retval" != 0 ]; then + return "$_retval" + fi + + ignore rm -rf "$_dir" + + # Install the install receipt + mkdir -p "$RECEIPT_HOME" || { + err "unable to create receipt directory at $RECEIPT_HOME" + } + echo "$RECEIPT" > "$RECEIPT_HOME/$APP_NAME-receipt.json" + # shellcheck disable=SC2320 + local _retval=$? + + return "$_retval" +} + +# Replaces $HOME with the variable name for display to the user, +# only if $HOME is defined. +replace_home() { + local _str="$1" + + if [ -n "${HOME:-}" ]; then + echo "$_str" | sed "s,$HOME,\$HOME," + else + echo "$_str" + fi +} + +json_binary_aliases() { + local _arch="$1" + + case "$_arch" in + "aarch64-apple-darwin") + echo '{}' + ;; + "x86_64-apple-darwin") + echo '{}' + ;; + "x86_64-pc-windows-gnu") + echo '{}' + ;; + "x86_64-unknown-linux-gnu") + echo '{}' + ;; + "x86_64-unknown-linux-musl-dynamic") + echo '{}' + ;; + "x86_64-unknown-linux-musl-static") + echo '{}' + ;; + *) + echo '{}' + ;; + esac +} + +aliases_for_binary() { + local _bin="$1" + local _arch="$2" + + case "$_arch" in + "aarch64-apple-darwin") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-apple-darwin") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-pc-windows-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-unknown-linux-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-unknown-linux-musl-dynamic") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-unknown-linux-musl-static") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + *) + echo "" + ;; + esac +} + +select_archive_for_arch() { + local _true_arch="$1" + local _archive + case "$_true_arch" in + "aarch64-apple-darwin") + _archive="lazygh-aarch64-apple-darwin.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + _archive="lazygh-x86_64-apple-darwin.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "aarch64-pc-windows-msvc") + _archive="lazygh-x86_64-pc-windows-msvc.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-apple-darwin") + _archive="lazygh-x86_64-apple-darwin.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-pc-windows-gnu") + _archive="lazygh-x86_64-pc-windows-msvc.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-pc-windows-msvc") + _archive="lazygh-x86_64-pc-windows-msvc.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-unknown-linux-gnu") + _archive="lazygh-x86_64-unknown-linux-gnu.tar.gz" + if ! check_glibc "2" "31"; then + _archive="" + fi + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + _archive="lazygh-x86_64-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-unknown-linux-musl-dynamic") + _archive="lazygh-x86_64-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-unknown-linux-musl-static") + _archive="lazygh-x86_64-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + *) + err "there isn't a download for your platform $_true_arch" + ;; + esac + err "no compatible downloads were found for your platform $_true_arch" +} + +check_glibc() { + local _min_glibc_major="$1" + local _min_glibc_series="$2" + + # Parsing version out from line 1 like: + # ldd (Ubuntu GLIBC 2.35-0ubuntu3.1) 2.35 + _local_glibc="$(ldd --version | awk -F' ' '{ if (FNR<=1) print $NF }')" + + if [ "$(echo "${_local_glibc}" | awk -F. '{ print $1 }')" = "$_min_glibc_major" ] && [ "$(echo "${_local_glibc}" | awk -F. '{ print $2 }')" -ge "$_min_glibc_series" ]; then + return 0 + else + say "System glibc version (\`${_local_glibc}') is too old; checking alternatives" >&2 + return 1 + fi +} + +# See discussion of late-bound vs early-bound for why we use single-quotes with env vars +# shellcheck disable=SC2016 +install() { + # This code needs to both compute certain paths for itself to write to, and + # also write them to shell/rc files so that they can look them up to e.g. + # add them to PATH. This requires an active distinction between paths + # and expressions that can compute them. + # + # The distinction lies in when we want env-vars to be evaluated. For instance + # if we determine that we want to install to $HOME/.myapp, which do we add + # to e.g. $HOME/.profile: + # + # * early-bound: export PATH="/home/myuser/.myapp:$PATH" + # * late-bound: export PATH="$HOME/.myapp:$PATH" + # + # In this case most people would prefer the late-bound version, but in other + # cases the early-bound version might be a better idea. In particular when using + # other env-vars than $HOME, they are more likely to be only set temporarily + # for the duration of this install script, so it's more advisable to erase their + # existence with early-bounding. + # + # This distinction is handled by "double-quotes" (early) vs 'single-quotes' (late). + # + # However if we detect that "$SOME_VAR/..." is a subdir of $HOME, we try to rewrite + # it to be '$HOME/...' to get the best of both worlds. + # + # This script has a few different variants, the most complex one being the + # CARGO_HOME version which attempts to install things to Cargo's bin dir, + # potentially setting up a minimal version if the user hasn't ever installed Cargo. + # + # In this case we need to: + # + # * Install to $HOME/.cargo/bin/ + # * Create a shell script at $HOME/.cargo/env that: + # * Checks if $HOME/.cargo/bin/ is on PATH + # * and if not prepends it to PATH + # * Edits $HOME/.profile to run $HOME/.cargo/env (if the line doesn't exist) + # + # To do this we need these 4 values: + + # The actual path we're going to install to + local _install_dir + # The directory C dynamic/static libraries install to + local _lib_install_dir + # The install prefix we write to the receipt. + # For organized install methods like CargoHome, which have + # subdirectories, this is the root without `/bin`. For other + # methods, this is the same as `_install_dir`. + local _receipt_install_dir + # Path to the an shell script that adds install_dir to PATH + local _env_script_path + # Potentially-late-bound version of install_dir to write env_script + local _install_dir_expr + # Potentially-late-bound version of env_script_path to write to rcfiles like $HOME/.profile + local _env_script_path_expr + # Forces the install to occur at this path, not the default + local _force_install_dir + + # Check the newer app-specific variable before falling back + # to the older generic one + if [ -n "${LAZYGH_INSTALL_DIR:-}" ]; then + _force_install_dir="$LAZYGH_INSTALL_DIR" + elif [ -n "${CARGO_DIST_FORCE_INSTALL_DIR:-}" ]; then + _force_install_dir="$CARGO_DIST_FORCE_INSTALL_DIR" + fi + + # Before actually consulting the configured install strategy, see + # if we're overriding it. + if [ -n "${_force_install_dir:-}" ]; then + _install_dir="$_force_install_dir/bin" + _lib_install_dir="$_force_install_dir/bin" + _receipt_install_dir="$_force_install_dir" + _env_script_path="$_force_install_dir/env" + _install_dir_expr="$(replace_home "$_force_install_dir/bin")" + _env_script_path_expr="$(replace_home "$_force_install_dir/env")" + fi + if [ -z "${_install_dir:-}" ]; then + # first try $CARGO_HOME, then fallback to $HOME/.cargo + if [ -n "${CARGO_HOME:-}" ]; then + _receipt_install_dir="$CARGO_HOME" + _install_dir="$CARGO_HOME/bin" + _lib_install_dir="$CARGO_HOME/bin" + _env_script_path="$CARGO_HOME/env" + # Initially make this early-bound to erase the potentially-temporary env-var + _install_dir_expr="$_install_dir" + _env_script_path_expr="$_env_script_path" + # If CARGO_HOME was set but it ended up being the default $HOME-based path, + # then keep things late-bound. Otherwise bake the value for safety. + # This is what rustup does, and accurately reproducing it is useful. + if [ -n "${HOME:-}" ]; then + if [ "$HOME/.cargo/bin" = "$_install_dir" ]; then + _install_dir_expr='$HOME/.cargo/bin' + _env_script_path_expr='$HOME/.cargo/env' + fi + fi + elif [ -n "${HOME:-}" ]; then + _receipt_install_dir="$HOME/.cargo" + _install_dir="$HOME/.cargo/bin" + _lib_install_dir="$HOME/.cargo/bin" + _env_script_path="$HOME/.cargo/env" + _install_dir_expr='$HOME/.cargo/bin' + _env_script_path_expr='$HOME/.cargo/env' + fi + fi + + if [ -z "$_install_dir_expr" ]; then + err "could not find a valid path to install to!" + fi + + # Identical to the sh version, just with a .fish file extension + # We place it down here to wait until it's been assigned in every + # path. + _fish_env_script_path="${_env_script_path}.fish" + _fish_env_script_path_expr="${_env_script_path_expr}.fish" + + # Replace the temporary cargo home with the calculated one + RECEIPT=$(echo "$RECEIPT" | sed "s,AXO_INSTALL_PREFIX,$_receipt_install_dir,") + # Also replace the aliases with the arch-specific one + RECEIPT=$(echo "$RECEIPT" | sed "s'\"binary_aliases\":{}'\"binary_aliases\":$(json_binary_aliases "$_arch")'") + + say "installing to $_install_dir" + ensure mkdir -p "$_install_dir" + ensure mkdir -p "$_lib_install_dir" + + # copy all the binaries to the install dir + local _src_dir="$1" + local _bins="$2" + local _libs="$3" + local _staticlibs="$4" + local _arch="$5" + for _bin_name in $_bins; do + local _bin="$_src_dir/$_bin_name" + ensure mv "$_bin" "$_install_dir" + # unzip seems to need this chmod + ensure chmod +x "$_install_dir/$_bin_name" + for _dest in $(aliases_for_binary "$_bin_name" "$_arch"); do + ln -sf "$_install_dir/$_bin_name" "$_install_dir/$_dest" + done + say " $_bin_name" + done + # Like the above, but no aliases + for _lib_name in $_libs; do + local _lib="$_src_dir/$_lib_name" + ensure mv "$_lib" "$_lib_install_dir" + # unzip seems to need this chmod + ensure chmod +x "$_lib_install_dir/$_lib_name" + say " $_lib_name" + done + for _lib_name in $_staticlibs; do + local _lib="$_src_dir/$_lib_name" + ensure mv "$_lib" "$_lib_install_dir" + # unzip seems to need this chmod + ensure chmod +x "$_lib_install_dir/$_lib_name" + say " $_lib_name" + done + + say "everything's installed!" + + # Avoid modifying the users PATH if they are managing their PATH manually + case :$PATH: + in *:$_install_dir:*) NO_MODIFY_PATH=1 ;; + *) ;; + esac + + if [ "0" = "$NO_MODIFY_PATH" ]; then + add_install_dir_to_ci_path "$_install_dir" + add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile" "sh" + exit1=$? + shotgun_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile .bashrc .bash_profile .bash_login" "sh" + exit2=$? + add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".zshrc .zshenv" "sh" + exit3=$? + # This path may not exist by default + ensure mkdir -p "$HOME/.config/fish/conf.d" + exit4=$? + add_install_dir_to_path "$_install_dir_expr" "$_fish_env_script_path" "$_fish_env_script_path_expr" ".config/fish/conf.d/$APP_NAME.env.fish" "fish" + exit5=$? + + if [ "${exit1:-0}" = 1 ] || [ "${exit2:-0}" = 1 ] || [ "${exit3:-0}" = 1 ] || [ "${exit4:-0}" = 1 ] || [ "${exit5:-0}" = 1 ]; then + say "" + say "To add $_install_dir_expr to your PATH, either restart your shell or run:" + say "" + say " source $_env_script_path_expr (sh, bash, zsh)" + say " source $_fish_env_script_path_expr (fish)" + fi + fi +} + +print_home_for_script() { + local script="$1" + + local _home + case "$script" in + # zsh has a special ZDOTDIR directory, which if set + # should be considered instead of $HOME + .zsh*) + if [ -n "${ZDOTDIR:-}" ]; then + _home="$ZDOTDIR" + else + _home="$HOME" + fi + ;; + *) + _home="$HOME" + ;; + esac + + echo "$_home" +} + +add_install_dir_to_ci_path() { + # Attempt to do CI-specific rituals to get the install-dir on PATH faster + local _install_dir="$1" + + # If GITHUB_PATH is present, then write install_dir to the file it refs. + # After each GitHub Action, the contents will be added to PATH. + # So if you put a curl | sh for this script in its own "run" step, + # the next step will have this dir on PATH. + # + # Note that GITHUB_PATH will not resolve any variables, so we in fact + # want to write install_dir and not install_dir_expr + if [ -n "${GITHUB_PATH:-}" ]; then + ensure echo "$_install_dir" >> "$GITHUB_PATH" + fi +} + +add_install_dir_to_path() { + # Edit rcfiles ($HOME/.profile) to add install_dir to $PATH + # + # We do this slightly indirectly by creating an "env" shell script which checks if install_dir + # is on $PATH already, and prepends it if not. The actual line we then add to rcfiles + # is to just source that script. This allows us to blast it into lots of different rcfiles and + # have it run multiple times without causing problems. It's also specifically compatible + # with the system rustup uses, so that we don't conflict with it. + local _install_dir_expr="$1" + local _env_script_path="$2" + local _env_script_path_expr="$3" + local _rcfiles="$4" + local _shell="$5" + + if [ -n "${HOME:-}" ]; then + local _target + local _home + + # Find the first file in the array that exists and choose + # that as our target to write to + for _rcfile_relative in $_rcfiles; do + _home="$(print_home_for_script "$_rcfile_relative")" + local _rcfile="$_home/$_rcfile_relative" + + if [ -f "$_rcfile" ]; then + _target="$_rcfile" + break + fi + done + + # If we didn't find anything, pick the first entry in the + # list as the default to create and write to + if [ -z "${_target:-}" ]; then + local _rcfile_relative + _rcfile_relative="$(echo "$_rcfiles" | awk '{ print $1 }')" + _home="$(print_home_for_script "$_rcfile_relative")" + _target="$_home/$_rcfile_relative" + fi + + # `source x` is an alias for `. x`, and the latter is more portable/actually-posix. + # This apparently comes up a lot on freebsd. It's easy enough to always add + # the more robust line to rcfiles, but when telling the user to apply the change + # to their current shell ". x" is pretty easy to misread/miscopy, so we use the + # prettier "source x" line there. Hopefully people with Weird Shells are aware + # this is a thing and know to tweak it (or just restart their shell). + local _robust_line=". \"$_env_script_path_expr\"" + local _pretty_line="source \"$_env_script_path_expr\"" + + # Add the env script if it doesn't already exist + if [ ! -f "$_env_script_path" ]; then + say_verbose "creating $_env_script_path" + if [ "$_shell" = "sh" ]; then + write_env_script_sh "$_install_dir_expr" "$_env_script_path" + else + write_env_script_fish "$_install_dir_expr" "$_env_script_path" + fi + else + say_verbose "$_env_script_path already exists" + fi + + # Check if the line is already in the rcfile + # grep: 0 if matched, 1 if no match, and 2 if an error occurred + # + # Ideally we could use quiet grep (-q), but that makes "match" and "error" + # have the same behaviour, when we want "no match" and "error" to be the same + # (on error we want to create the file, which >> conveniently does) + # + # We search for both kinds of line here just to do the right thing in more cases. + if ! grep -F "$_robust_line" "$_target" > /dev/null 2>/dev/null && \ + ! grep -F "$_pretty_line" "$_target" > /dev/null 2>/dev/null + then + # If the script now exists, add the line to source it to the rcfile + # (This will also create the rcfile if it doesn't exist) + if [ -f "$_env_script_path" ]; then + local _line + # Fish has deprecated `.` as an alias for `source` and + # it will be removed in a later version. + # https://fishshell.com/docs/current/cmds/source.html + # By contrast, `.` is the traditional syntax in sh and + # `source` isn't always supported in all circumstances. + if [ "$_shell" = "fish" ]; then + _line="$_pretty_line" + else + _line="$_robust_line" + fi + say_verbose "adding $_line to $_target" + # prepend an extra newline in case the user's file is missing a trailing one + ensure echo "" >> "$_target" + ensure echo "$_line" >> "$_target" + return 1 + fi + else + say_verbose "$_install_dir already on PATH" + fi + fi +} + +shotgun_install_dir_to_path() { + # Edit rcfiles ($HOME/.profile) to add install_dir to $PATH + # (Shotgun edition - write to all provided files that exist rather than just the first) + local _install_dir_expr="$1" + local _env_script_path="$2" + local _env_script_path_expr="$3" + local _rcfiles="$4" + local _shell="$5" + + if [ -n "${HOME:-}" ]; then + local _found=false + local _home + + for _rcfile_relative in $_rcfiles; do + _home="$(print_home_for_script "$_rcfile_relative")" + local _rcfile_abs="$_home/$_rcfile_relative" + + if [ -f "$_rcfile_abs" ]; then + _found=true + add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfile_relative" "$_shell" + fi + done + + # Fall through to previous "create + write to first file in list" behavior + if [ "$_found" = false ]; then + add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfiles" "$_shell" + fi + fi +} + +write_env_script_sh() { + # write this env script to the given path (this cat/EOF stuff is a "heredoc" string) + local _install_dir_expr="$1" + local _env_script_path="$2" + ensure cat < "$_env_script_path" +#!/bin/sh +# add binaries to PATH if they aren't added yet +# affix colons on either side of \$PATH to simplify matching +case ":\${PATH}:" in + *:"$_install_dir_expr":*) + ;; + *) + # Prepending path in case a system-installed binary needs to be overridden + export PATH="$_install_dir_expr:\$PATH" + ;; +esac +EOF +} + +write_env_script_fish() { + # write this env script to the given path (this cat/EOF stuff is a "heredoc" string) + local _install_dir_expr="$1" + local _env_script_path="$2" + ensure cat < "$_env_script_path" +if not contains "$_install_dir_expr" \$PATH + # Prepending path in case a system-installed binary needs to be overridden + set -x PATH "$_install_dir_expr" \$PATH +end +EOF +} + +check_proc() { + # Check for /proc by looking for the /proc/self/exe link + # This is only run on Linux + if ! test -L /proc/self/exe ; then + err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc." + fi +} + +get_bitness() { + need_cmd head + # Architecture detection without dependencies beyond coreutils. + # ELF files start out "\x7fELF", and the following byte is + # 0x01 for 32-bit and + # 0x02 for 64-bit. + # The printf builtin on some shells like dash only supports octal + # escape sequences, so we use those. + local _current_exe_head + _current_exe_head=$(head -c 5 /proc/self/exe ) + if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then + echo 32 + elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then + echo 64 + else + err "unknown platform bitness" + fi +} + +is_host_amd64_elf() { + need_cmd head + need_cmd tail + # ELF e_machine detection without dependencies beyond coreutils. + # Two-byte field at offset 0x12 indicates the CPU, + # but we're interested in it being 0x3E to indicate amd64, or not that. + local _current_exe_machine + _current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1) + [ "$_current_exe_machine" = "$(printf '\076')" ] +} + +get_endianness() { + local cputype=$1 + local suffix_eb=$2 + local suffix_el=$3 + + # detect endianness without od/hexdump, like get_bitness() does. + need_cmd head + need_cmd tail + + local _current_exe_endianness + _current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)" + if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then + echo "${cputype}${suffix_el}" + elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then + echo "${cputype}${suffix_eb}" + else + err "unknown platform endianness" + fi +} + +get_architecture() { + local _ostype + local _cputype + _ostype="$(uname -s)" + _cputype="$(uname -m)" + local _clibtype="gnu" + local _local_glibc + + if [ "$_ostype" = Linux ]; then + if [ "$(uname -o)" = Android ]; then + _ostype=Android + fi + if ldd --version 2>&1 | grep -q 'musl'; then + _clibtype="musl-dynamic" + else + # Assume all other linuxes are glibc (even if wrong, static libc fallback will apply) + _clibtype="gnu" + fi + fi + + if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then + # Darwin `uname -m` lies + if sysctl hw.optional.x86_64 | grep -q ': 1'; then + _cputype=x86_64 + fi + fi + + if [ "$_ostype" = Darwin ] && [ "$_cputype" = x86_64 ]; then + # Rosetta on aarch64 + if [ "$(sysctl -n hw.optional.arm64 2>/dev/null)" = "1" ]; then + _cputype=aarch64 + fi + fi + + if [ "$_ostype" = SunOS ]; then + # Both Solaris and illumos presently announce as "SunOS" in "uname -s" + # so use "uname -o" to disambiguate. We use the full path to the + # system uname in case the user has coreutils uname first in PATH, + # which has historically sometimes printed the wrong value here. + if [ "$(/usr/bin/uname -o)" = illumos ]; then + _ostype=illumos + fi + + # illumos systems have multi-arch userlands, and "uname -m" reports the + # machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86 + # systems. Check for the native (widest) instruction set on the + # running kernel: + if [ "$_cputype" = i86pc ]; then + _cputype="$(isainfo -n)" + fi + fi + + case "$_ostype" in + + Android) + _ostype=linux-android + ;; + + Linux) + check_proc + _ostype=unknown-linux-$_clibtype + _bitness=$(get_bitness) + ;; + + FreeBSD) + _ostype=unknown-freebsd + ;; + + NetBSD) + _ostype=unknown-netbsd + ;; + + DragonFly) + _ostype=unknown-dragonfly + ;; + + Darwin) + _ostype=apple-darwin + ;; + + illumos) + _ostype=unknown-illumos + ;; + + MINGW* | MSYS* | CYGWIN* | Windows_NT) + _ostype=pc-windows-gnu + ;; + + *) + err "unrecognized OS type: $_ostype" + ;; + + esac + + case "$_cputype" in + + i386 | i486 | i686 | i786 | x86) + _cputype=i686 + ;; + + xscale | arm) + _cputype=arm + if [ "$_ostype" = "linux-android" ]; then + _ostype=linux-androideabi + fi + ;; + + armv6l) + _cputype=arm + if [ "$_ostype" = "linux-android" ]; then + _ostype=linux-androideabi + else + _ostype="${_ostype}eabihf" + fi + ;; + + armv7l | armv8l) + _cputype=armv7 + if [ "$_ostype" = "linux-android" ]; then + _ostype=linux-androideabi + else + _ostype="${_ostype}eabihf" + fi + ;; + + aarch64 | arm64) + _cputype=aarch64 + ;; + + x86_64 | x86-64 | x64 | amd64) + _cputype=x86_64 + ;; + + mips) + _cputype=$(get_endianness mips '' el) + ;; + + mips64) + if [ "$_bitness" -eq 64 ]; then + # only n64 ABI is supported for now + _ostype="${_ostype}abi64" + _cputype=$(get_endianness mips64 '' el) + fi + ;; + + ppc) + _cputype=powerpc + ;; + + ppc64) + _cputype=powerpc64 + ;; + + ppc64le) + _cputype=powerpc64le + ;; + + s390x) + _cputype=s390x + ;; + riscv64) + _cputype=riscv64gc + ;; + loongarch64) + _cputype=loongarch64 + ;; + *) + err "unknown CPU type: $_cputype" + + esac + + # Detect 64-bit linux with 32-bit userland + if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then + case $_cputype in + x86_64) + # 32-bit executable for amd64 = x32 + if is_host_amd64_elf; then { + err "x32 linux unsupported" + }; else + _cputype=i686 + fi + ;; + mips64) + _cputype=$(get_endianness mips '' el) + ;; + powerpc64) + _cputype=powerpc + ;; + aarch64) + _cputype=armv7 + if [ "$_ostype" = "linux-android" ]; then + _ostype=linux-androideabi + else + _ostype="${_ostype}eabihf" + fi + ;; + riscv64gc) + err "riscv64 with 32-bit userland unsupported" + ;; + esac + fi + + # treat armv7 systems without neon as plain arm + if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then + if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then + # At least one processor does not have NEON. + _cputype=arm + fi + fi + + _arch="${_cputype}-${_ostype}" + + RETVAL="$_arch" +} + +say() { + if [ "0" = "$PRINT_QUIET" ]; then + echo "$1" + fi +} + +say_verbose() { + if [ "1" = "$PRINT_VERBOSE" ]; then + echo "$1" + fi +} + +err() { + if [ "0" = "$PRINT_QUIET" ]; then + local red + local reset + red=$(tput setaf 1 2>/dev/null || echo '') + reset=$(tput sgr0 2>/dev/null || echo '') + say "${red}ERROR${reset}: $1" >&2 + fi + exit 1 +} + +need_cmd() { + if ! check_cmd "$1" + then err "need '$1' (command not found)" + fi +} + +check_cmd() { + command -v "$1" > /dev/null 2>&1 + return $? +} + +assert_nz() { + if [ -z "$1" ]; then err "assert_nz $2"; fi +} + +# Run a command that should never fail. If the command fails execution +# will immediately terminate with an error showing the failing +# command. +ensure() { + if ! "$@"; then err "command failed: $*"; fi +} + +# This is just for indicating that commands' results are being +# intentionally ignored. Usually, because it's being executed +# as part of error handling. +ignore() { + "$@" +} + +# This wraps curl or wget. Try curl first, if not installed, +# use wget instead. +downloader() { + if check_cmd curl + then _dld=curl + elif check_cmd wget + then _dld=wget + else _dld='curl or wget' # to be used in error message of need_cmd + fi + + if [ "$1" = --check ] + then need_cmd "$_dld" + elif [ "$_dld" = curl ] + then curl -sSfL "$1" -o "$2" + elif [ "$_dld" = wget ] + then wget "$1" -O "$2" + else err "Unknown downloader" # should not reach here + fi +} + +download_binary_and_run_installer "$@" || exit 1 diff --git a/oranda-v0.6.1.css b/oranda-v0.6.1.css new file mode 100644 index 0000000..2845f5e --- /dev/null +++ b/oranda-v0.6.1.css @@ -0,0 +1,3 @@ +@import url("https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;700;900&display=swap");@import url("https://fonts.googleapis.com/css2?family=Comfortaa:wght@400;700&display=swap");@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600;700&display=swap");@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap");:root{--dark-fg-color:#fff;--light-fg-color:#141414;--light-bg-color:var(--dark-fg-color);--dark-bg-color:var(--light-fg-color);--fg-color:var(--light-fg-color);--bg-color:var(--light-bg-color);--light-link-color:#0284c7;--dark-link-color:#8bb9fe;--link-color:var(--light-link-color);--light-highlight-bg-color:#ededed;--light-highlight-fg-color:#595959;--dark-highlight-bg-color:#27272a;--dark-highlight-fg-color:#ededed;--highlight-fg-color:var(--light-highlight-fg-color);--highlight-bg-color:var(--light-highlight-bg-color);--font-face:"Fira Sans",sans-serif}:root.dark{--fg-color:var(--dark-fg-color);--bg-color:var(--dark-bg-color);--link-color:var(--dark-link-color);--highlight-fg-color:var(--dark-highlight-fg-color);--highlight-bg-color:var(--dark-highlight-bg-color)} + +/*! tailwindcss v3.4.0 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}:host,html{-webkit-text-size-adjust:100%;font-feature-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-variation-settings:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-feature-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{font-feature-settings:inherit;color:inherit;font-family:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{--tw-shadow:0 0 #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-radius:0;border-width:1px;font-size:1rem;line-height:1.5rem;padding:.5rem .75rem}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);border-color:#2563eb;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);outline:2px solid #0000;outline-offset:2px}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-bottom:0;padding-top:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{--tw-shadow:0 0 #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;background-origin:border-box;border-color:#6b7280;border-width:1px;color:#2563eb;display:inline-block;flex-shrink:0;height:1rem;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:1rem}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);outline:2px solid #0000;outline-offset:2px}[type=checkbox]:checked,[type=radio]:checked{background-color:currentColor;background-position:50%;background-repeat:no-repeat;background-size:100% 100%;border-color:#0000}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=checkbox]:indeterminate,[type=radio]:checked:focus,[type=radio]:checked:hover{background-color:currentColor;border-color:#0000}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:100% 100%}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{background-color:currentColor;border-color:#0000}[type=file]{background:unset;border-color:inherit;border-radius:0;border-width:0;font-size:unset;line-height:inherit;padding:0}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}:root{--color-inherit:inherit;--color-current:currentColor;--color-transparent:#0000;--color-black:#000;--color-white:#fff;--color-slate-50:#f8fafc;--color-slate-100:#f1f5f9;--color-slate-200:#e2e8f0;--color-slate-300:#cbd5e1;--color-slate-400:#94a3b8;--color-slate-500:#64748b;--color-slate-600:#475569;--color-slate-700:#334155;--color-slate-800:#1e293b;--color-slate-900:#0f172a;--color-slate-950:#020617;--color-gray-50:#f9fafb;--color-gray-100:#f3f4f6;--color-gray-200:#e5e7eb;--color-gray-300:#d1d5db;--color-gray-400:#9ca3af;--color-gray-500:#6b7280;--color-gray-600:#4b5563;--color-gray-700:#374151;--color-gray-800:#1f2937;--color-gray-900:#111827;--color-gray-950:#030712;--color-zinc-50:#fafafa;--color-zinc-100:#f4f4f5;--color-zinc-200:#e4e4e7;--color-zinc-300:#d4d4d8;--color-zinc-400:#a1a1aa;--color-zinc-500:#71717a;--color-zinc-600:#52525b;--color-zinc-700:#3f3f46;--color-zinc-800:#27272a;--color-zinc-900:#18181b;--color-zinc-950:#09090b;--color-neutral-50:#fafafa;--color-neutral-100:#f5f5f5;--color-neutral-200:#e5e5e5;--color-neutral-300:#d4d4d4;--color-neutral-400:#a3a3a3;--color-neutral-500:#737373;--color-neutral-600:#525252;--color-neutral-700:#404040;--color-neutral-800:#262626;--color-neutral-900:#171717;--color-neutral-950:#0a0a0a;--color-stone-50:#fafaf9;--color-stone-100:#f5f5f4;--color-stone-200:#e7e5e4;--color-stone-300:#d6d3d1;--color-stone-400:#a8a29e;--color-stone-500:#78716c;--color-stone-600:#57534e;--color-stone-700:#44403c;--color-stone-800:#292524;--color-stone-900:#1c1917;--color-stone-950:#0c0a09;--color-red-50:#fef2f2;--color-red-100:#fee2e2;--color-red-200:#fecaca;--color-red-300:#fca5a5;--color-red-400:#f87171;--color-red-500:#ef4444;--color-red-600:#dc2626;--color-red-700:#b91c1c;--color-red-800:#991b1b;--color-red-900:#7f1d1d;--color-red-950:#450a0a;--color-orange-50:#fff7ed;--color-orange-100:#ffedd5;--color-orange-200:#fed7aa;--color-orange-300:#fdba74;--color-orange-400:#fb923c;--color-orange-500:#f97316;--color-orange-600:#ea580c;--color-orange-700:#c2410c;--color-orange-800:#9a3412;--color-orange-900:#7c2d12;--color-orange-950:#431407;--color-amber-50:#fffbeb;--color-amber-100:#fef3c7;--color-amber-200:#fde68a;--color-amber-300:#fcd34d;--color-amber-400:#fbbf24;--color-amber-500:#f59e0b;--color-amber-600:#d97706;--color-amber-700:#b45309;--color-amber-800:#92400e;--color-amber-900:#78350f;--color-amber-950:#451a03;--color-yellow-50:#fefce8;--color-yellow-100:#fef9c3;--color-yellow-200:#fef08a;--color-yellow-300:#fde047;--color-yellow-400:#facc15;--color-yellow-500:#eab308;--color-yellow-600:#ca8a04;--color-yellow-700:#a16207;--color-yellow-800:#854d0e;--color-yellow-900:#713f12;--color-yellow-950:#422006;--color-lime-50:#f7fee7;--color-lime-100:#ecfccb;--color-lime-200:#d9f99d;--color-lime-300:#bef264;--color-lime-400:#a3e635;--color-lime-500:#84cc16;--color-lime-600:#65a30d;--color-lime-700:#4d7c0f;--color-lime-800:#3f6212;--color-lime-900:#365314;--color-lime-950:#1a2e05;--color-green-50:#f0fdf4;--color-green-100:#dcfce7;--color-green-200:#bbf7d0;--color-green-300:#86efac;--color-green-400:#4ade80;--color-green-500:#22c55e;--color-green-600:#16a34a;--color-green-700:#15803d;--color-green-800:#166534;--color-green-900:#14532d;--color-green-950:#052e16;--color-emerald-50:#ecfdf5;--color-emerald-100:#d1fae5;--color-emerald-200:#a7f3d0;--color-emerald-300:#6ee7b7;--color-emerald-400:#34d399;--color-emerald-500:#10b981;--color-emerald-600:#059669;--color-emerald-700:#047857;--color-emerald-800:#065f46;--color-emerald-900:#064e3b;--color-emerald-950:#022c22;--color-teal-50:#f0fdfa;--color-teal-100:#ccfbf1;--color-teal-200:#99f6e4;--color-teal-300:#5eead4;--color-teal-400:#2dd4bf;--color-teal-500:#14b8a6;--color-teal-600:#0d9488;--color-teal-700:#0f766e;--color-teal-800:#115e59;--color-teal-900:#134e4a;--color-teal-950:#042f2e;--color-cyan-50:#ecfeff;--color-cyan-100:#cffafe;--color-cyan-200:#a5f3fc;--color-cyan-300:#67e8f9;--color-cyan-400:#22d3ee;--color-cyan-500:#06b6d4;--color-cyan-600:#0891b2;--color-cyan-700:#0e7490;--color-cyan-800:#155e75;--color-cyan-900:#164e63;--color-cyan-950:#083344;--color-sky-50:#f0f9ff;--color-sky-100:#e0f2fe;--color-sky-200:#bae6fd;--color-sky-300:#7dd3fc;--color-sky-400:#38bdf8;--color-sky-500:#0ea5e9;--color-sky-600:#0284c7;--color-sky-700:#0369a1;--color-sky-800:#075985;--color-sky-900:#0c4a6e;--color-sky-950:#082f49;--color-blue-50:#eff6ff;--color-blue-100:#dbeafe;--color-blue-200:#bfdbfe;--color-blue-300:#93c5fd;--color-blue-400:#60a5fa;--color-blue-500:#3b82f6;--color-blue-600:#2563eb;--color-blue-700:#1d4ed8;--color-blue-800:#1e40af;--color-blue-900:#1e3a8a;--color-blue-950:#172554;--color-indigo-50:#eef2ff;--color-indigo-100:#e0e7ff;--color-indigo-200:#c7d2fe;--color-indigo-300:#a5b4fc;--color-indigo-400:#818cf8;--color-indigo-500:#6366f1;--color-indigo-600:#4f46e5;--color-indigo-700:#4338ca;--color-indigo-800:#3730a3;--color-indigo-900:#312e81;--color-indigo-950:#1e1b4b;--color-violet-50:#f5f3ff;--color-violet-100:#ede9fe;--color-violet-200:#ddd6fe;--color-violet-300:#c4b5fd;--color-violet-400:#a78bfa;--color-violet-500:#8b5cf6;--color-violet-600:#7c3aed;--color-violet-700:#6d28d9;--color-violet-800:#5b21b6;--color-violet-900:#4c1d95;--color-violet-950:#2e1065;--color-purple-50:#faf5ff;--color-purple-100:#f3e8ff;--color-purple-200:#e9d5ff;--color-purple-300:#d8b4fe;--color-purple-400:#c084fc;--color-purple-500:#a855f7;--color-purple-600:#9333ea;--color-purple-700:#7e22ce;--color-purple-800:#6b21a8;--color-purple-900:#581c87;--color-purple-950:#3b0764;--color-fuchsia-50:#fdf4ff;--color-fuchsia-100:#fae8ff;--color-fuchsia-200:#f5d0fe;--color-fuchsia-300:#f0abfc;--color-fuchsia-400:#e879f9;--color-fuchsia-500:#d946ef;--color-fuchsia-600:#c026d3;--color-fuchsia-700:#a21caf;--color-fuchsia-800:#86198f;--color-fuchsia-900:#701a75;--color-fuchsia-950:#4a044e;--color-pink-50:#fdf2f8;--color-pink-100:#fce7f3;--color-pink-200:#fbcfe8;--color-pink-300:#f9a8d4;--color-pink-400:#f472b6;--color-pink-500:#ec4899;--color-pink-600:#db2777;--color-pink-700:#be185d;--color-pink-800:#9d174d;--color-pink-900:#831843;--color-pink-950:#500724;--color-rose-50:#fff1f2;--color-rose-100:#ffe4e6;--color-rose-200:#fecdd3;--color-rose-300:#fda4af;--color-rose-400:#fb7185;--color-rose-500:#f43f5e;--color-rose-600:#e11d48;--color-rose-700:#be123c;--color-rose-800:#9f1239;--color-rose-900:#881337;--color-rose-950:#4c0519;--color-axo-pink:#ff75c3;--color-axo-pink-dark:#cc5c9b;--color-axo-orange:#f57070;--color-axo-orange-dark:#e85e68;--color-axo-highlighter:#ffd900;--color-axo-black:#141414;--color-axo-light-gray:#ededed;--color-axo-dark-gray:#595959}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }body,html{font-family:var(--font-face);height:100%;scroll-behavior:smooth}.container{display:flex;flex-direction:column;min-height:100%}.page-body{flex-grow:1}:focus{outline-offset:4px;outline-style:solid;outline-width:2px}body{background-color:var(--bg-color);color:var(--fg-color)}a{color:var(--link-color)}a:hover{text-decoration-line:underline;text-underline-offset:4px}.title{font-size:3.75rem;line-height:1;padding-bottom:.5rem;text-align:center}@media (min-width:640px){.title{font-size:6rem;line-height:1}}h1{font-size:1.875rem;font-weight:900;line-height:2.25rem;line-height:1.25;margin-bottom:2rem}@media (min-width:640px){h1{font-size:3.75rem;line-height:1}}h2{font-size:1.5rem;font-weight:700;line-height:2rem;line-height:1.25;margin-bottom:1.5rem}@media (min-width:640px){h2{font-size:3rem;line-height:1}}h2,h3{margin-top:3rem}@media (min-width:640px){h2,h3{margin-top:6rem}}h3{font-size:1.5rem;font-weight:700;line-height:2rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){h3{font-size:2.25rem;line-height:2.5rem}}h4{font-size:1.5rem;line-height:2rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){h4{font-size:1.875rem;line-height:2.25rem}}h5{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity));font-size:1.25rem;font-weight:700;line-height:1.75rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){h5{font-size:1.5rem;line-height:2rem}}:is(:where(.dark) h5){--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity))}h6{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity));font-size:1.25rem;font-weight:700;line-height:1.75rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){h6{font-size:1.25rem;line-height:1.75rem}}:is(:where(.dark) h6){--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity))}p,table{font-size:1rem;line-height:1.5rem;line-height:1.625;margin-bottom:2rem}@media (min-width:640px){p,table{font-size:1.125rem;line-height:1.75rem}}b,li{font-size:1rem;line-height:1.5rem;line-height:1.625}@media (min-width:640px){b,li{font-size:1.125rem;line-height:1.75rem}}table{margin-bottom:4rem;margin-top:4rem}table th{padding:1rem;text-align:left;text-transform:uppercase}table td{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;padding:1rem;vertical-align:top}table td,table td>code{font-size:.875rem;line-height:1.25rem}table tbody tr{border-color:var(--fg-color);border-top-width:1px}div.table{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));margin-bottom:4rem;margin-top:4rem;width:100%}div.table .th{font-size:1.125rem;font-weight:700;line-height:1.75rem;text-align:left;text-transform:uppercase}div.table .th,div.table span:not(.th){border-color:var(--fg-color);border-top-width:1px;padding:1rem}div.table span:not(.th){font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:.875rem;line-height:1.25rem}li,ul{list-style-type:none}.rendered-markdown li,.rendered-markdown ul{list-style-type:disc}li{margin-bottom:1rem;margin-left:1rem}@media (min-width:640px){li{margin-left:2rem}}code{font-size:1rem;line-height:1.5rem;line-height:1.625;margin-bottom:1rem;white-space:pre-wrap}@media (min-width:640px){code{font-size:1.125rem;line-height:1.75rem}}code{color:var(--link-color)}div.table code{font-size:.875rem;line-height:1.25rem}h1 code,h2 code,h3 code,h4 code,h5 code,h6 code{font-size:inherit;line-height:inherit}pre{margin-bottom:4rem;margin-top:4rem;overflow:auto;padding:1rem}pre>code{font-size:.75rem;line-height:1rem}@media (min-width:640px){pre>code{font-size:1rem;line-height:1.5rem}}hr{border-style:dashed;border-width:1px;margin:5rem auto;text-align:center;width:16rem}@media (min-width:768px){hr{width:24rem}}img{display:inline}p>img:only-child{display:block;margin:auto}blockquote{border-color:var(--link-color);border-left-width:2px;font-size:1.5rem;line-height:2rem;padding-left:1.5rem}main{margin:6rem auto;max-width:80%}@media (min-width:1024px){main{max-width:56rem}}.github-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E");height:1.25rem;width:1.25rem}.dark .github-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23141414' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")}.dark .artifacts,.light .artifacts{padding:2rem}.logo{display:block;margin:auto;max-width:20rem}.inline-code{text-align:center;word-break:break-all}.oblique{font-style:oblique}.well-color{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.oranda-hide{display:none}.heading-1{font-size:1.875rem;font-weight:900;line-height:2.25rem;line-height:1.25;margin-bottom:2rem}@media (min-width:640px){.heading-1{font-size:3.75rem;line-height:1}}.heading-2{font-size:1.5rem;font-weight:700;line-height:2rem;line-height:1.25;margin-bottom:1.5rem}@media (min-width:640px){.heading-2{font-size:3rem;line-height:1}}.heading-3{font-size:1.5rem;font-weight:700;line-height:2rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){.heading-3{font-size:2.25rem;line-height:2.5rem}}.heading-4{font-size:1.5rem;line-height:2rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){.heading-4{font-size:1.875rem;line-height:2.25rem}}.heading-5{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity));font-size:1.25rem;font-weight:700;line-height:1.75rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){.heading-5{font-size:1.5rem;line-height:2rem}}:is(:where(.dark) .heading-5){--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity))}.heading-6{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity));font-size:1.25rem;font-weight:700;line-height:1.75rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){.heading-6{font-size:1.25rem;line-height:1.75rem}}:is(:where(.dark) .heading-6){--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity))}.hidden{display:none}.inline-icon>svg{display:inline-block;height:25px;width:25px}.button{border-radius:.25rem;border-width:2px;cursor:pointer;font-size:1.125rem;line-height:1.75rem;min-width:-moz-max-content;min-width:max-content;padding:.75rem;transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);width:10rem}.button:disabled{cursor:default;opacity:.6}.button.primary{border-color:#0000}.button.primary,.button.secondary{background-color:var(--bg-color);color:var(--fg-color)}.button.secondary{border-color:var(--fg-color)}.button.secondary:hover{background-color:var(--fg-color);border-color:var(--bg-color);color:var(--bg-color)}select{background-color:var(--bg-color);color:var(--fg-color)}footer{align-items:center;background-color:var(--fg-color);color:var(--bg-color);display:flex;flex-grow:0;flex-shrink:1;font-size:.75rem;justify-content:space-between;line-height:1rem;padding:.5rem 1rem;width:100%}.nav{margin-bottom:3rem}.nav,.nav ul{padding:0;text-align:center}.nav ul{align-items:center;display:flex;flex-wrap:wrap;gap:1.5rem;justify-content:center;list-style-type:none}.nav ul li{margin:0;text-transform:capitalize}.repo_banner{background-color:var(--fg-color);color:var(--bg-color);padding-bottom:.375rem;padding-top:.375rem}.repo_banner>a{align-items:flex-start;display:flex;gap:.5rem;height:20px;justify-content:center}.repo_banner>a,.repo_banner>a:hover{--tw-text-opacity:1;color:rgb(248 250 252/var(--tw-text-opacity))}.repo_banner>a:hover{text-decoration-color:#f8fafc;text-decoration-line:underline;text-underline-offset:1px}:is(:where(.dark) .repo_banner>a){color:#141414}:is(:where(.dark) .repo_banner>a:hover){color:#141414;text-decoration-color:#141414}.funding-wrapper{align-items:center;display:flex;flex-direction:column;margin-top:2rem}.funding-list{gap:1rem;grid-template-columns:repeat(2,minmax(0,1fr));margin-bottom:3rem;margin-top:3rem;width:100%}@media (min-width:1024px){.funding-list{display:grid}}.funding-list li{margin:0 0 1rem}.funding-list li a{align-items:center;display:flex;gap:.5rem}.funding-list li a:hover button{--tw-text-opacity:1;background-color:#e85e68;background-color:var(--fg-color);border-color:#e85e68;border-color:var(--bg-color);color:rgb(241 245 249/var(--tw-text-opacity));color:var(--bg-color)}.funding-list .button{display:block;margin-right:.5rem;width:auto}.preferred-funding-list{grid-template-columns:repeat(1,minmax(0,1fr))}.preferred-funding-list li a{flex-direction:column;font-size:2.25rem;font-weight:700;line-height:2.5rem}.preferred-funding-list svg{height:3rem;width:3rem}.preferred-funding-list .button{border-width:0}.package-managers-downloads ul{margin-bottom:4rem;margin-top:4rem}.package-managers-downloads ul li{margin-left:0}.package-managers-downloads pre{margin-bottom:0;margin-top:0}.artifacts{align-items:center;display:none;flex-direction:column;margin-bottom:2rem;padding:0}@media (min-width:640px){.artifacts{display:flex}}.artifacts{background-color:var(--highlight-bg-color);color:var(--highlight-fg-color)}.artifacts-table{display:block;max-width:100%;overflow:auto}ul.tabs{border-bottom-width:2px;border-color:var(--highlight-fg-color);display:flex}ul.tabs li{font-size:1rem;line-height:1.5rem;margin:0;padding:.5rem .75rem}ul.tabs li:hover{cursor:pointer}ul.tabs li small{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity));display:block;font-size:.75rem;line-height:1rem}ul.tabs li.selected,ul.tabs li.selected small{background-color:var(--highlight-fg-color);color:var(--highlight-bg-color)}.install-content{margin:0;max-width:100%;padding:0}.detect{padding-right:.5rem;text-align:center}@media (min-width:768px){.detect{padding-right:0}}.detect+a{display:block;margin-bottom:.5rem;margin-top:.5rem}@media (min-width:640px){.detect+a{display:inline;margin-bottom:0;margin-top:0}}.detect .detected-os{text-transform:capitalize}.artifact-header pre{margin:0 auto}.artifact-header>h4{font-weight:700;margin-bottom:-.5rem;text-align:center}.artifact-header{max-width:100%;width:100%}.artifact-header>div:not(.install-code-wrapper){align-items:center;justify-content:center;margin-top:1rem;text-align:center}@media (min-width:768px){.artifact-header>div:not(.install-code-wrapper){display:flex;gap:1rem;text-align:left}}.backup-download:hover{text-decoration-line:none}.bottom-options{align-items:center;display:flex;flex-direction:row;justify-content:space-between;width:100%}.bottom-options.one{justify-content:center}.install-code-wrapper{align-items:stretch;display:flex}.install-code-wrapper>pre{flex-grow:1;flex-shrink:1}.install-code-wrapper>.button{align-items:center;border-bottom-left-radius:0;border-top-left-radius:0;display:flex;width:auto}.install-code-wrapper>.button:hover{text-decoration-line:none}.install-code-wrapper>.button:focus{outline-offset:-2px}.install-code-wrapper>.button.copy-clipboard-button{border-radius:0}.download-wrapper{display:flex;flex-direction:row;justify-content:center}.button .button-subtitle{display:block;font-size:.75rem;line-height:1rem}.published-date{display:block;margin-bottom:.5rem}.arch{margin:0;padding:1rem 0 0}.arch .contents{min-height:7rem;padding-top:1rem}.mobile-download{display:block;margin-bottom:3rem;margin-left:auto;margin-right:auto}@media (min-width:640px){.mobile-download{display:none}}.install-code-wrapper>.button svg{height:1.5rem;width:1.5rem}.release-body{margin-top:2rem;word-break:break-word}.release-body h1{font-size:1.5rem;font-weight:700;line-height:2rem;line-height:1.25;margin-bottom:1.5rem;margin-top:3rem}@media (min-width:640px){.release-body h1{font-size:3rem;line-height:1}}.release-body h2{font-size:1.5rem;font-weight:700;line-height:2rem;line-height:1.25;margin-bottom:1rem;margin-top:3rem}@media (min-width:640px){.release-body h2{font-size:2.25rem;line-height:2.5rem}}.release-body h3{font-size:1.5rem;line-height:2rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){.release-body h3{font-size:1.875rem;line-height:2.25rem}}.release-body h4{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity));font-size:1.25rem;font-weight:700;line-height:1.75rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){.release-body h4{font-size:1.5rem;line-height:2rem}}:is(:where(.dark) .release-body h4){--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity))}.release-body h5{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity));font-size:1.25rem;font-weight:700;line-height:1.75rem;line-height:1.25;margin-bottom:1rem}@media (min-width:640px){.release-body h5{font-size:1.25rem;line-height:1.75rem}}:is(:where(.dark) .release-body h5){--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity))}.release-body li,.release-body ul{list-style-type:disc}.releases-nav{align-self:flex-start;position:sticky;top:3rem;width:-moz-max-content;width:max-content}.release>h2{margin-top:0}.release>h2 a{color:var(--fg-color)}.releases-list{display:flex;flex-direction:column;gap:8rem}.releases-wrapper{gap:3rem;margin-top:3rem;position:relative}@media (min-width:768px){.releases-wrapper{display:grid}}.releases-wrapper{grid-template-columns:160px minmax(0,1fr)}.releases-nav ul{border-left-width:4px;display:none;flex-direction:column;gap:.5rem;list-style-type:none;margin:0;padding-left:1rem}@media (min-width:768px){.releases-nav ul{display:flex}}.releases-nav ul{border-color:var(--fg-color)}.releases-nav ul li{font-size:.875rem;line-height:1.25rem;margin:0 0 0 .25rem;position:relative}.releases-nav ul li:before{--tw-translate-y:-50%;background-color:var(--fg-color);content:"";display:block;height:.25rem;left:-1.25rem;position:absolute;top:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));width:1rem}.releases-nav ul li a{text-decoration-color:#0000;text-underline-offset:2px}.releases-nav ul li a:hover{text-decoration-line:underline}.releases-nav ul li a{color:var(--fg-color)}.release-info{display:flex;font-size:1rem;gap:2rem;line-height:1.5rem}.prereleases-toggle,.release-info{align-items:center}.prereleases-toggle{display:none;margin-bottom:1.5rem;position:relative;width:-moz-max-content;width:max-content}@media (min-width:768px){.prereleases-toggle{display:flex}}.prereleases-toggle input{border-radius:.25rem;color:var(--fg-color);height:1.25rem;width:1.25rem}.prereleases-toggle label{font-weight:500;margin-left:.75rem}.release-info svg{height:1.5rem;width:1.5rem}.release-info>span{align-items:center;display:flex;gap:.5rem}ul.index-grid{align-items:stretch;display:grid;gap:2rem;margin-top:4rem}@media (min-width:768px){ul.index-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){ul.index-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}.index-grid li{border-color:var(--bg-color);border-radius:.25rem;border-width:1px;box-shadow:0 0 0 8px #0000004d;flex-direction:column;margin-left:0}.index-grid .content,.index-grid li{display:flex;justify-content:space-between}.index-grid .content{padding:1rem}.index-grid .links{display:flex;width:100%}.index-grid .links>:not([hidden])~:not([hidden]){--tw-divide-x-reverse:0;border-left-width:calc(1px*(1 - var(--tw-divide-x-reverse)));border-right-width:calc(1px*var(--tw-divide-x-reverse))}.index-grid .links{border-top-width:1px}.index-grid .links a{align-items:center;display:inline-flex;width:50%}.index-grid .links a>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.index-grid .links a{padding:1rem 1.5rem}.index-grid .content .index-logo{flex-shrink:0;height:5rem;position:relative;width:5rem}.index-grid li.preferred{grid-column:span 2/span 2}.index-about h2{margin-top:0}html.axo{--highlight-color:#a78bfa;--axo-orange-color:#f57070;--axo-pink-color:#ff75c3;--light-fg-color:#141414;--light-link-color:var(--axo-pink-color);--dark-link-color:var(--axo-pink-color);--light-highlight-bg-color:var(--light-bg-color);--light-highlight-fg-color:var(--light-fg-color);--dark-highlight-bg-color:var(--light-fg-color);--dark-highlight-fg-color:var(--light-bg-color);--font-face:"Comfortaa",sans-serif}code,h1,h2,h3{color:var(--highlight-color)}html.axo .button.primary{background-color:var(--link-color)}html.axo .repo_banner,html.axo footer{animation-duration:3s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:animation-gradient-title;background:-webkit-linear-gradient(left,var(--axo-orange-color),var(--axo-pink-color),var(--axo-orange-color));background-size:1600px 200px}@media (prefers-reduced-motion){html.axo .repo_banner,html.axo footer{animation-duration:0s}}html.hacker html.axo .repo_banner,html.hacker html.axo footer{background:-webkit-linear-gradient(left,var(--hacker-green),var(--color-green-600),var(--hacker-green))}html.cupcake html.axo .repo_banner,html.cupcake html.axo footer{background:var(--secondary)}html.axo h1.title{-webkit-text-fill-color:#0000;animation-duration:3s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:animation-gradient-title;background:-webkit-linear-gradient(left,var(--axo-orange-color),var(--axo-pink-color),var(--axo-orange-color));background-size:1600px 200px}@media (prefers-reduced-motion){html.axo h1.title{animation-duration:0s}}html.hacker html.axo h1.title{background:-webkit-linear-gradient(left,var(--hacker-green),var(--color-green-600),var(--hacker-green))}html.cupcake html.axo h1.title{background:var(--secondary)}html.axo h1.title{-webkit-background-clip:text;background-clip:text}.axo-gradient{animation-duration:3s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:animation-gradient-title;background:-webkit-linear-gradient(left,var(--axo-orange-color),var(--axo-pink-color),var(--axo-orange-color));background-size:1600px 200px}.text-fill-transparent{-webkit-text-fill-color:#0000}.axo-gradient-text{-webkit-text-fill-color:#0000;animation-duration:3s;animation-fill-mode:forwards;animation-iteration-count:infinite;animation-name:animation-gradient-title;background:-webkit-linear-gradient(left,var(--axo-orange-color),var(--axo-pink-color),var(--axo-orange-color));background-size:1600px 200px}@media (prefers-reduced-motion){.axo-gradient-text{animation-duration:0s}}html.hacker .axo-gradient-text{background:-webkit-linear-gradient(left,var(--hacker-green),var(--color-green-600),var(--hacker-green))}html.cupcake .axo-gradient-text{background:var(--secondary)}.axo-gradient-text{-webkit-background-clip:text;background-clip:text}@media (prefers-reduced-motion){.axo-gradient{animation-duration:0s}}@keyframes slide-in{0%{top:-100vh}to{top:0}}@keyframes animation-gradient-title{0%{background-position:0 1600px}to{background-position:1600px 0}}html.hacker{--light-highlight-bg-color:var(--dark-highlight-bg-color);--light-highlight-fg-color:var(--dark-highlight-fg-color);--hacker-green:#20c20e}html.hacker ::-moz-selection{background-color:#20c20e;color:#141414}html.hacker ::selection{background-color:#20c20e;color:#141414}html.hacker body{--tw-text-opacity:1;background-color:#141414;font-family:IBM Plex Mono,monospace}html.hacker .button.secondary,html.hacker body{color:rgb(203 213 225/var(--tw-text-opacity))}html.hacker .button.secondary{--tw-border-opacity:1;--tw-text-opacity:1;border-color:rgb(249 115 22/var(--tw-border-opacity))}html.hacker .button.secondary:hover{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity));color:#141414}html.hacker h2,html.hacker h3,html.hacker h4,html.hacker h5,html.hacker h6{--tw-text-opacity:1;color:rgb(124 58 237/var(--tw-text-opacity))}html.hacker .repo_banner>a,html.hacker footer{color:var(--light-color);padding-bottom:.5rem;padding-top:.5rem}html.hacker p,html.hacker table{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity))}html.hacker .title{display:inline-block;margin-left:2rem;position:relative;text-align:left}@keyframes blink-animation{to{visibility:hidden}}html.hacker .title:after{animation:blink-animation 1s steps(5,start) infinite;background:var(--hacker-green);content:"";display:block;height:70px;left:100%;margin-left:.75rem;position:absolute;top:.75rem;width:1rem}html.hacker .title:before{--tw-translate-y:-50%;--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity));content:"> ";display:block;font-size:3rem;left:-2rem;line-height:1;margin-top:.5rem;position:absolute;top:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}html.hacker .title,html.hacker div.table .th,html.hacker h1{color:var(--hacker-green)}html.hacker a{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity))}html.hacker a:hover{text-decoration-color:#f97316}html.hacker .axo-gradient{background:-webkit-linear-gradient(left,var(--hacker-green),var(--color-green-600),var(--hacker-green))}html.hacker .nav ul{justify-content:flex-start}html.hacker .button.primary{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity));border-color:#0000;color:#141414}html.hacker .button.primary:hover{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity))}html.hacker .artifact-header>h4{color:var(--light-color);text-align:left}html.hacker .releases-nav ul li a{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity))}html.hacker .releases-nav ul li:before{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}html.hacker .releases-nav ul{--tw-border-opacity:1;border-left-color:rgb(75 85 99/var(--tw-border-opacity))}html.hacker .prereleases-toggle input:checked{--tw-bg-opacity:1;background-color:rgb(249 115 22/var(--tw-bg-opacity))}html.hacker .releases-nav ul li a:hover{text-decoration-color:#f97316}html.hacker .funding-wrapper{align-items:flex-start}html.hacker .artifacts{padding:2rem}html.hacker .published-date{display:block;width:100%}html.hacker .logo{display:block;margin:0}html.cupcake body{--b1:#faf7f5;--b2:#dfaff7;--text:#291334cc;--links:#291334;--primary:#65c3c8;--secondary:#291334;--secondary-100:#210f2a;--code:#291334;background-color:var(--b1);color:var(--text);font-family:Inter,sans-serif}html.cupcake ::-moz-selection{-webkit-text-fill-color:var(--code);background-color:var(--b2);color:var(--code)}html.cupcake ::selection{-webkit-text-fill-color:var(--code);background-color:var(--b2);color:var(--code)}html.cupcake .button.primary{background:var(--secondary);border-color:#0000;color:var(--b2);text-decoration-line:none}html.cupcake .button.primary:hover{--tw-bg-opacity:1;background-color:rgb(234 88 12/var(--tw-bg-opacity));background:var(--secondary-100)}html.cupcake .button.secondary{border:1px solid var(--secondary);color:var(--secondary-100)}html.cupcake .button.secondary:hover{background:var(--secondary);color:var(--b2)}html.cupcake h1,html.cupcake h2,html.cupcake h3,html.cupcake h4,html.cupcake h5,html.cupcake h6,html.cupcake p,html.cupcake table{color:var(--text)}html.cupcake .title{color:var(--primary)}html.cupcake a{color:var(--links);font-weight:500;text-decoration-line:underline;text-underline-offset:4px}html.cupcake a:hover{color:var(--code);text-underline-offset:2px}html.cupcake .axo-gradient{background:var(--secondary)}html.cupcake .github-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23dfaff7' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")}html.cupcake .repo_banner>a,html.cupcake footer{color:var(--b2);text-decoration:none}html.cupcake code{color:var(--code);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-weight:500}html.cupcake .prereleases-toggle input:checked{background-color:var(--primary)}html.cupcake .artifacts{padding:2rem}html.cupcake .releases-nav ul li a{color:var(--links)}html.cupcake .releases-nav ul li:before{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}html.cupcake .releases-nav ul{--tw-border-opacity:1;border-left-color:rgb(209 213 219/var(--tw-border-opacity))}html.cupcake div.table .th{color:var(--primary)} \ No newline at end of file