diff options
| author | 2026-02-23 09:02:43 -0800 | |
|---|---|---|
| committer | 2026-02-23 09:04:00 -0800 | |
| commit | 12894d7dd9471cd08807cb2245529b94c77f5bff (patch) | |
| tree | 480ecb7a1dcad2155a08f246d3d78a6266df0406 /glide | |
| parent | f75a9bad45b5fa5b7de987bfd8ebdc24459ad5a7 (diff) | |
| download | new-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.ts | 89 |
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" }); |
