aboutsummaryrefslogtreecommitdiffstats
path: root/glide
diff options
context:
space:
mode:
authorGravatar Tom Willemse2026-02-23 09:02:43 -0800
committerGravatar Tom Willemse2026-02-23 09:04:00 -0800
commit12894d7dd9471cd08807cb2245529b94c77f5bff (patch)
tree480ecb7a1dcad2155a08f246d3d78a6266df0406 /glide
parentf75a9bad45b5fa5b7de987bfd8ebdc24459ad5a7 (diff)
downloadnew-dotfiles-12894d7dd9471cd08807cb2245529b94c77f5bff.tar.gz
new-dotfiles-12894d7dd9471cd08807cb2245529b94c77f5bff.zip
glide: Add function to pick a heading to show
Got it from the configuration showcase: https://github.com/glide-browser/glide/discussions/147#discussioncomment-15617575
Diffstat (limited to 'glide')
-rw-r--r--glide/.config/glide/glide.ts89
1 files changed, 89 insertions, 0 deletions
diff --git a/glide/.config/glide/glide.ts b/glide/.config/glide/glide.ts
index 4600988..678b876 100644
--- a/glide/.config/glide/glide.ts
+++ b/glide/.config/glide/glide.ts
@@ -161,3 +161,92 @@ glide.keymaps.set('normal', '<leader>gd', async function() {
});
glide.addons.install("https://addons.mozilla.org/firefox/downloads/file/4675310/ublock_origin-1.69.0.xpi");
+
+// From https://github.com/glide-browser/glide/discussions/147#discussioncomment-15617575
+
+interface Heading {
+ text: string;
+ tag: string;
+ id: string;
+ xpath: string;
+}
+
+glide.keymaps.set("normal", "gh", async () => {
+ const activeTabId = await glide.tabs.active();
+
+ // Extract all visible headings from the page
+ const headings = await glide.content.execute((): Heading[] => {
+ function isVisible(element: HTMLElement): boolean {
+ const style = window.getComputedStyle(element);
+ return style.display !== 'none' &&
+ style.visibility !== 'hidden' &&
+ style.opacity !== '0' &&
+ element.offsetParent !== null;
+ }
+
+ function getXPath(element: Element): string {
+ let path = '';
+ for (let el: Element | null = element; el && el.nodeType === Node.ELEMENT_NODE; el = el.parentElement) {
+ let index = 0;
+ for (let sibling = el.previousSibling; sibling; sibling = sibling.previousSibling) {
+ if (sibling.nodeType === Node.ELEMENT_NODE && (sibling as Element).tagName === el.tagName) {
+ index++;
+ }
+ }
+ const tagName = el.tagName.toLowerCase();
+ const pathIndex = `[${index + 1}]`;
+ path = `/${tagName}${pathIndex}${path}`;
+ }
+ return path;
+ }
+
+ return Array.from(document.querySelectorAll('h1, h2, h3, h4, h5, h6'))
+ .filter((heading) => isVisible(heading as HTMLElement))
+ .map((heading): Heading => ({
+ text: heading.textContent?.trim() || '',
+ tag: heading.tagName.toLowerCase(),
+ id: heading.id || '',
+ xpath: getXPath(heading)
+ }));
+ }, { tab_id: activeTabId });
+
+ if (headings.length === 0) {
+ glide.commandline.show({
+ title: "No visible headings found",
+ options: []
+ });
+ return;
+ }
+
+ glide.commandline.show({
+ title: "Jump to heading",
+ options: headings.map((heading) => {
+ const level = parseInt(heading.tag.substring(1));
+ const indent = '*'.repeat(level);
+
+ return {
+ label: `${indent}${indent ? ' ' : ''}${heading.text}`,
+ async execute() {
+ await glide.content.execute((xpath: string) => {
+ const target = document.evaluate(
+ xpath,
+ document,
+ null,
+ XPathResult.FIRST_ORDERED_NODE_TYPE,
+ null
+ ).singleNodeValue as HTMLElement | null;
+
+ if (target) {
+ target.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ target.style.outline = '2px solid orange';
+ setTimeout(() => { target.style.outline = ''; }, 2000);
+ }
+ }, {
+ tab_id: activeTabId,
+ args: [heading.xpath]
+ });
+ },
+ };
+ }),
+ });
+}, { description: "Jump to heading in current page" });