glide: initial config
change rtqvskzukxowmwzskzkxrowwuttzlptx
commit 0e3ba8a5d437db7e6f35d084dce9fa0712abaee1
author Alpha Chen <alpha@kejadlen.dev>
date
parent uzxtprmk
diff --git a/.config/glide/.gitignore b/.config/glide/.gitignore
new file mode 100644
index 00000000..92677af0
--- /dev/null
+++ b/.config/glide/.gitignore
@@ -0,0 +1,2 @@
+# this is a 10k+ line file that's provided by glide anyway
+glide.d.ts
diff --git a/.config/glide/glide.ts b/.config/glide/glide.ts
new file mode 100644
index 00000000..082f9cb4
--- /dev/null
+++ b/.config/glide/glide.ts
@@ -0,0 +1,89 @@
+// Config docs:
+//
+//   https://glide-browser.app/config
+//
+// API reference:
+//
+//   https://glide-browser.app/api
+//
+// Default config files can be found here:
+//
+//   https://github.com/glide-browser/glide/tree/main/src/glide/browser/base/content/plugins
+//
+// Most default keymappings are defined here:
+//
+//   https://github.com/glide-browser/glide/blob/main/src/glide/browser/base/content/plugins/keymaps.mts
+//
+// Try typing `glide.` and see what you can do!
+
+glide.unstable.include("hints.glide.ts");
+
+glide.styles.add(`
+  .yank-notification {
+    position: fixed;
+    bottom: 2rem;
+    right: 2rem;
+    z-index: 2147483646;
+    background: var(--glide-cmdl-bg);
+    color: var(--glide-cmdl-fg);
+    border: 1px solid hsla(0, 0%, 100%, 0.1);
+    border-radius: 4px;
+    box-shadow: 0 -8px 32px hsla(0, 0%, 0%, 0.4);
+    font-family: var(--glide-cmdl-font-family);
+    font-size: var(--glide-cmdl-font-size);
+    line-height: var(--glide-cmdl-line-height);
+    padding: 0.75rem 1rem;
+    max-width: 600px;
+    word-break: break-all;
+  }
+`);
+
+glide.keymaps.set("normal", "zi", async ({ tab_id }) => {
+  const zoom = await browser.tabs.getZoom(tab_id);
+  await browser.tabs.setZoom(tab_id, zoom + 0.1);
+});
+
+glide.keymaps.set("normal", "zo", async ({ tab_id }) => {
+  const zoom = await browser.tabs.getZoom(tab_id);
+  await browser.tabs.setZoom(tab_id, zoom - 0.1);
+});
+
+glide.keymaps.set("normal", "zz", async ({ tab_id }) => {
+  await browser.tabs.setZoom(tab_id, 1);
+});
+
+glide.keymaps.set("normal", "u", async () => {
+  const sessions = await browser.sessions.getRecentlyClosed({ maxResults: 1 });
+  const [session, ..._] = sessions;
+  if (session) {
+    await browser.sessions.restore(session.tab?.sessionId ?? session.window?.sessionId);
+  }
+});
+
+glide.keymaps.set("normal", "H", "back");
+glide.keymaps.set("normal", "L", "forward");
+glide.keymaps.set("normal", "d", "tab_close");
+
+glide.keymaps.set("normal", "p", async ({ tab_id }) => {
+  const url = await navigator.clipboard.readText();
+  await browser.tabs.update(tab_id, { url });
+});
+
+glide.keymaps.set("normal", "P", async () => {
+  const url = await navigator.clipboard.readText();
+  await browser.tabs.create({ url });
+});
+
+glide.keymaps.set("normal", "yy", async () => {
+  const url = glide.ctx.url;
+  await navigator.clipboard.writeText(url.toString());
+
+  const notification = DOM.create_element("div", {
+    className: "yank-notification",
+    textContent: `Yanked: ${url}`,
+  });
+
+  document.documentElement.appendChild(notification);
+  setTimeout(() => notification.remove(), 2000);
+});
+
diff --git a/.config/glide/hints.glide.ts b/.config/glide/hints.glide.ts
new file mode 100644
index 00000000..3c0f18cd
--- /dev/null
+++ b/.config/glide/hints.glide.ts
@@ -0,0 +1,79 @@
+// Source: https://github.com/jyn514/dotfiles/blob/master/config/glide.ts
+
+function shorten_unique_prefixes(haystack) {
+  // first, construct a set of duplicates
+  const seen = new Set();
+  const duplicates = new Set();
+  for (let t of haystack) {
+    if (seen.has(t)) {
+      duplicates.add(t);
+    } else {
+      seen.add(t);
+    }
+  }
+
+  // shorten each word
+  return haystack.map((needle, pos) => {
+    if (duplicates.has(needle)) return needle;
+    // while all words have the same character at position i, increment i
+    for (let i = 1; i <= needle.length; i++) {
+      const prefix = needle.slice(0, i);
+      const is_unique = haystack.every((w, j) => pos === j || !w.startsWith(prefix));
+      if (is_unique) {
+        return prefix;
+      }
+    }
+    // no unique prefix
+    return needle;
+  });
+}
+
+function strip(text) {
+  // strip numbers, non-ascii text, and annoying-to-type characters
+  return text.replace(/[0-9]+/g, '').replace(/[^a-zA-Z0-9-]/g, '').toLowerCase();
+}
+
+function labels(texts) {
+  // now shorten as much as we can without losing info
+  const haystack = shorten_unique_prefixes(texts);
+
+  let nums_used = 0;
+  const result = new Array(haystack.length);
+
+  // trim prefixes longer than 3 characters by using letters that occur later in the label.
+  // also, try to replace the last letter of duplicates.
+  // note that that can only help if the original text was > 3 characters.
+  const used = new Set();
+  outer: for (const [index, prefix] of haystack.entries()) {
+    if (prefix === "") {
+      result[index] = String(nums_used++);
+    } else if (prefix.length > 3 || used.has(prefix)) {
+      const base = prefix.substring(0, 2);
+      // try each character after the 3rd in turn.
+      // consider the original text, not the shortened prefix.
+      for (const c of texts[index].substring(2)) {
+        const candidate = base + c;
+        if (!used.has(candidate)) {
+          result[index] = candidate;
+          used.add(candidate);
+          continue outer;
+        }
+      }
+      // we couldn't shorten it. use a number.
+      result[index] = String(nums_used++);
+    } else {
+      // already short enough, use it as-is.
+      result[index] = prefix;
+      used.add(prefix);
+    }
+  }
+
+  // try one last time to shorten prefixes—if we gave up earlier, we might have freed up a spot.
+  return shorten_unique_prefixes(result);
+}
+
+glide.o.hint_label_generator = async ({ content }) => {
+  const texts = await content.map(element => [element.textContent, element.ariaLabel]);
+  const haystack = texts.map(([text, label]) => strip(text) || strip(label || ""));
+  return labels(haystack);
+};
diff --git a/.config/glide/package.json b/.config/glide/package.json
new file mode 100644
index 00000000..18866382
--- /dev/null
+++ b/.config/glide/package.json
@@ -0,0 +1,16 @@
+{
+  "name": "glide-config",
+  "private": true,
+  "version": "0.0.1",
+  "description": "",
+  "scripts": {
+    "tsc": "tsc"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "",
+  "dependencies": {
+    "typescript": "^5.9.2"
+  },
+  "devDependencies": {}
+}
\ No newline at end of file
diff --git a/.config/glide/tsconfig.json b/.config/glide/tsconfig.json
new file mode 100644
index 00000000..e6bdc203
--- /dev/null
+++ b/.config/glide/tsconfig.json
@@ -0,0 +1,38 @@
+{
+  "$schema": "https://json.schemastore.org/tsconfig",
+  "exclude": [
+    "node_modules"
+  ],
+  "compilerOptions": {
+    "lib": ["DOM", "DOM.Iterable", "DOM.AsyncIterable", "ESNext"],
+    "types": [
+      "./glide.d.ts"
+    ],
+    "target": "esnext",
+    "module": "esnext",
+    "moduleDetection": "force",
+    "allowJs": true,
+    "noEmit": true,
+    /**
+     * Recommended type checking rules.
+     *
+     * Feel free to modify these.
+     */
+    "strict": true,
+    "noImplicitAny": true,
+    "strictNullChecks": true,
+    "strictFunctionTypes": true,
+    "strictBindCallApply": true,
+    "strictPropertyInitialization": true,
+    "noImplicitThis": true,
+    "alwaysStrict": true,
+    "noUncheckedIndexedAccess": true,
+    "noImplicitOverride": true,
+    "noPropertyAccessFromIndexSignature": true,
+    "skipLibCheck": true,
+    "noErrorTruncation": true,
+    "erasableSyntaxOnly": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true
+  }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index d0de0b04..b79413af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@ private
 !.config/fish
 !.config/git
 !.config/ghostty
+!.config/glide
 !.config/irb
 .config/irb/irb_history
 !.config/jj