summaryrefslogtreecommitdiff
path: root/public
diff options
context:
space:
mode:
Diffstat (limited to 'public')
-rw-r--r--public/footnotes.js2
-rw-r--r--public/my_uptime.js2
-rw-r--r--public/scrollbar.js21
-rw-r--r--public/shell.js128
-rw-r--r--public/styles/style.css105
5 files changed, 88 insertions, 170 deletions
diff --git a/public/footnotes.js b/public/footnotes.js
index 57ded98..96a9400 100644
--- a/public/footnotes.js
+++ b/public/footnotes.js
@@ -8,7 +8,7 @@ const SIDENOTES = {
readingWidth: null, // max width of the post text, null = no cap
};
-document.addEventListener("DOMContentLoaded", () => {
+document.addEventListener("htmx:load", () => {
const area = document.querySelector("[data-scroll-area]");
const article = area?.querySelector("article");
if (!area || !article) return;
diff --git a/public/my_uptime.js b/public/my_uptime.js
index 1fdb457..b5f3ca2 100644
--- a/public/my_uptime.js
+++ b/public/my_uptime.js
@@ -13,7 +13,7 @@ async function updateUptime() {
}
// Run on page load after all DOM elements loaded
-document.addEventListener("DOMContentLoaded", () => {
+document.addEventListener("htmx:load", () => {
updateUptime();
setInterval(updateUptime, 5 * 1000); // in ms
});
diff --git a/public/scrollbar.js b/public/scrollbar.js
index 2218b55..b297d76 100644
--- a/public/scrollbar.js
+++ b/public/scrollbar.js
@@ -1,4 +1,8 @@
function initScrollbox(box) {
+ // Guard against double-initialization
+ if (box.dataset.initialized) return;
+ box.dataset.initialized = "true";
+
const area = box.querySelector("[data-scroll-area]");
const track = box.querySelector("[data-scroll-track]");
const thumb = box.querySelector("[data-scroll-thumb]");
@@ -51,23 +55,26 @@ function initScrollbox(box) {
document.querySelectorAll("[data-scrollbox]").forEach(initScrollbox);
-// Vim style j/k scrolling
+document.addEventListener("htmx:afterSettle", () => {
+ document.querySelectorAll("[data-scrollbox]").forEach(initScrollbox);
+});
+
document.addEventListener("keydown", (e) => {
- // Don't scroll in input elements
- const tag = document.activeElement.tagName;
+ const tag = document.activeElement?.tagName;
if (
["INPUT", "TEXTAREA", "SELECT"].includes(tag) ||
- document.activeElement.isContentEditable
+ document.activeElement?.isContentEditable
) {
return;
}
- // Only work for "j" and "k", no ctrl/alt/shift
if (e.ctrlKey || e.altKey || e.metaKey) return;
+ if (e.key !== "j" && e.key !== "k") return;
- const dir = key === "j" ? step : -step;
- const scrollTarget = document.scrollingElement || document.documentElement;
const scrollAmount = 100; // in pixels
+ const dir = e.key === "j" ? scrollAmount : -scrollAmount;
+ const scrollTarget = document.scrollingElement || document.documentElement;
+
if (scrollTarget && scrollTarget.scrollHeight > scrollTarget.clientHeight) {
scrollTarget.scrollBy({ top: dir, behavior: "auto" });
} else {
diff --git a/public/shell.js b/public/shell.js
index 9a70846..3f3aef8 100644
--- a/public/shell.js
+++ b/public/shell.js
@@ -1,73 +1,75 @@
-const shell = document.querySelector("[data-shell]");
+document.addEventListener("htmx:load", () => {
+ const shell = document.querySelector("[data-shell]");
-if (shell) {
- const area = shell.closest("[data-scroll-area]");
- const history = shell.querySelector("#shell-history");
- const input = shell.querySelector("[data-shell-input]");
- const caret = shell.querySelector("[data-shell-caret]");
- let busy = false;
+ if (shell) {
+ const area = shell.closest("[data-scroll-area]");
+ const history = shell.querySelector("#shell-history");
+ const input = shell.querySelector("[data-shell-input]");
+ const caret = shell.querySelector("[data-shell-caret]");
+ let busy = false;
- const updateCaret = () => {
- const pos = input.selectionStart ?? input.value.length;
- caret.style.left = `calc(${pos}ch - ${input.scrollLeft}px)`;
- caret.textContent = input.value[pos] ?? "\u00a0";
- caret.style.animation = "none"; // restart the blink so the caret is solid while typing
- void caret.offsetWidth;
- caret.style.animation = "";
- };
+ const updateCaret = () => {
+ const pos = input.selectionStart ?? input.value.length;
+ caret.style.left = `calc(${pos}ch - ${input.scrollLeft}px)`;
+ caret.textContent = input.value[pos] ?? "\u00a0";
+ caret.style.animation = "none"; // restart the blink so the caret is solid while typing
+ void caret.offsetWidth;
+ caret.style.animation = "";
+ };
- const snapToBottom = () => {
- area.scrollTop = area.scrollHeight;
- };
+ const snapToBottom = () => {
+ area.scrollTop = area.scrollHeight;
+ };
- const run = async (cmd) => {
- busy = true;
- try {
- const res = await fetch("/shell/run", {
- method: "POST",
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
- body: new URLSearchParams({ cmd }),
- });
- const data = await res.json();
- if (data.clear) history.replaceChildren();
- if (data.html) history.insertAdjacentHTML("beforeend", data.html);
- if (data.vars) {
- for (const [key, value] of Object.entries(data.vars)) {
- document.documentElement.style.setProperty(`--${key}`, value);
+ const run = async (cmd) => {
+ busy = true;
+ try {
+ const res = await fetch("/shell/run", {
+ method: "POST",
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
+ body: new URLSearchParams({ cmd }),
+ });
+ const data = await res.json();
+ if (data.clear) history.replaceChildren();
+ if (data.html) history.insertAdjacentHTML("beforeend", data.html);
+ if (data.vars) {
+ for (const [key, value] of Object.entries(data.vars)) {
+ document.documentElement.style.setProperty(`--${key}`, value);
+ }
}
+ } catch {
+ const el = document.createElement("p");
+ el.textContent = "request failed";
+ history.append(el);
+ } finally {
+ busy = false;
+ snapToBottom();
}
- } catch {
- const el = document.createElement("p");
- el.textContent = "request failed";
- history.append(el);
- } finally {
- busy = false;
- snapToBottom();
- }
- };
+ };
- input.addEventListener("keydown", (e) => {
- if (e.key !== "Enter") return;
- e.preventDefault();
- const cmd = input.value.trim();
- if (!cmd || busy) return;
- input.value = "";
- updateCaret();
- run(cmd);
- });
+ input.addEventListener("keydown", (e) => {
+ if (e.key !== "Enter") return;
+ e.preventDefault();
+ const cmd = input.value.trim();
+ if (!cmd || busy) return;
+ input.value = "";
+ updateCaret();
+ run(cmd);
+ });
- for (const event of ["input", "keyup", "click", "focus"]) {
- input.addEventListener(event, updateCaret);
- }
- document.addEventListener("selectionchange", () => {
- if (document.activeElement === input) updateCaret();
- });
+ for (const event of ["input", "keyup", "click", "focus"]) {
+ input.addEventListener(event, updateCaret);
+ }
+ document.addEventListener("selectionchange", () => {
+ if (document.activeElement === input) updateCaret();
+ });
- area.addEventListener("click", () => {
- if (!getSelection().toString()) input.focus({ preventScroll: true });
- });
+ area.addEventListener("click", () => {
+ if (!getSelection().toString()) input.focus({ preventScroll: true });
+ });
- input.focus({ preventScroll: true });
- updateCaret();
- snapToBottom();
-}
+ input.focus({ preventScroll: true });
+ updateCaret();
+ snapToBottom();
+ }
+});
diff --git a/public/styles/style.css b/public/styles/style.css
index 3610b64..76bf2a1 100644
--- a/public/styles/style.css
+++ b/public/styles/style.css
@@ -823,26 +823,12 @@
.pointer-events-none {
pointer-events: none;
}
- .collapse {
- visibility: collapse;
- }
.invisible {
visibility: hidden;
}
.visible {
visibility: visible;
}
- .sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip-path: inset(50%);
- white-space: nowrap;
- border-width: 0;
- }
.absolute {
position: absolute;
}
@@ -861,9 +847,6 @@
.inset-y-0 {
inset-block: 0px;
}
- .top-1 {
- top: var(--spacing);
- }
.top-1\/2 {
top: calc(1 / 2 * 100%);
}
@@ -903,24 +886,6 @@
.col-span-2 {
grid-column: span 2 / span 2;
}
- .container {
- width: 100%;
- @media (width >= 40rem) {
- max-width: 40rem;
- }
- @media (width >= 48rem) {
- max-width: 48rem;
- }
- @media (width >= 64rem) {
- max-width: 64rem;
- }
- @media (width >= 80rem) {
- max-width: 80rem;
- }
- @media (width >= 96rem) {
- max-width: 96rem;
- }
- }
.-m-\[0\.4rem\] {
margin: calc(0.4rem * -1);
}
@@ -1441,9 +1406,6 @@
.hidden {
display: none;
}
- .inline {
- display: inline;
- }
.inline-block {
display: inline-block;
}
@@ -1531,33 +1493,17 @@
.flex-1 {
flex: 1;
}
- .flex-shrink {
- flex-shrink: 1;
- }
.shrink-0 {
flex-shrink: 0;
}
- .flex-grow {
- flex-grow: 1;
- }
- .grow {
- flex-grow: 1;
- }
- .border-collapse {
- border-collapse: collapse;
- }
- .-translate-y-1 {
- --tw-translate-y: calc(var(--spacing) * -1);
- translate: var(--tw-translate-x) var(--tw-translate-y);
- }
.-translate-y-1\/2 {
--tw-translate-y: calc(calc(1 / 2 * 100%) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
- .scale-150 {
- --tw-scale-x: 150%;
- --tw-scale-y: 150%;
- --tw-scale-z: 150%;
+ .scale-135 {
+ --tw-scale-x: 135%;
+ --tw-scale-y: 135%;
+ --tw-scale-z: 135%;
scale: var(--tw-scale-x) var(--tw-scale-y);
}
.transform {
@@ -1783,9 +1729,6 @@
.bg-\[var\(--text\)\] {
background-color: var(--text);
}
- .bg-black {
- background-color: var(--color-black);
- }
.bg-black\/20 {
background-color: color-mix(in srgb, #000 20%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -1801,9 +1744,6 @@
.bg-transparent {
background-color: transparent;
}
- .bg-white {
- background-color: var(--color-white);
- }
.bg-white\/2 {
background-color: color-mix(in srgb, #fff 2%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -1822,9 +1762,6 @@
.bg-\[linear-gradient\(to_bottom\,var\(--background\)\,var\(--cmp-bg\,transparent\)\)\] {
background-image: linear-gradient(to bottom,var(--background),var(--cmp-bg,transparent));
}
- .mask-repeat {
- mask-repeat: repeat;
- }
.fill-\[\#7ed4fb\]\/50 {
fill: color-mix(in oklab, #7ed4fb 50%, transparent);
}
@@ -1864,9 +1801,6 @@
.p-\[3vw\] {
padding: 3vw;
}
- .px-3 {
- padding-inline: calc(var(--spacing) * 3);
- }
.px-3\.5 {
padding-inline: calc(var(--spacing) * 3.5);
}
@@ -1981,15 +1915,15 @@
.text-\[85\%\] {
font-size: 85%;
}
- .text-\[90\%\] {
- font-size: 90%;
- }
.text-\[95\%\] {
font-size: 95%;
}
.text-\[110\%\] {
font-size: 110%;
}
+ .text-\[120\%\] {
+ font-size: 120%;
+ }
.text-\[130\%\] {
font-size: 130%;
}
@@ -2122,15 +2056,9 @@
.text-\[var\(--secondary\)\] {
color: var(--secondary);
}
- .italic {
- font-style: italic;
- }
.no-underline {
text-decoration-line: none;
}
- .underline {
- text-decoration-line: underline;
- }
.caret-transparent {
caret-color: transparent;
}
@@ -2144,19 +2072,6 @@
}
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
- .ring {
- --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
- }
- .outline {
- outline-style: var(--tw-outline-style);
- outline-width: 1px;
- }
- .transition {
- transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
- transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
- transition-duration: var(--tw-duration, var(--default-transition-duration));
- }
.transition-colors {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
@@ -2781,11 +2696,6 @@ body {
inherits: false;
initial-value: 0 0 #0000;
}
-@property --tw-outline-style {
- syntax: "*";
- inherits: false;
- initial-value: solid;
-}
@property --tw-duration {
syntax: "*";
inherits: false;
@@ -2827,7 +2737,6 @@ body {
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-offset-shadow: 0 0 #0000;
- --tw-outline-style: solid;
--tw-duration: initial;
--tw-content: "";
}