/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // main.ts var main_exports = {}; __export(main_exports, { default: () => LinkPreviewPlugin }); module.exports = __toCommonJS(main_exports); var import_obsidian = require("obsidian"); var DEFAULT_SETTINGS = { previewDelay: 300, maxPreviewHeight: 400, maxPreviewWidth: 600 }; var LinkPreviewPlugin = class extends import_obsidian.Plugin { constructor() { super(...arguments); // Track active preview elements by link URL this.activeLinks = /* @__PURE__ */ new Map(); } async onload() { await this.loadSettings(); this.registerHoverHandler(document); this.registerEvent( this.app.workspace.on("window-open", ({ win }) => { this.registerHoverHandler(win.document); }) ); this.addSettingTab(new LinkPreviewSettingTab(this.app, this)); } registerHoverHandler(doc) { this.registerDomEvent(doc, "mouseover", (evt) => { const target = evt.target; const linkEl = target.closest("a"); if (!linkEl) return; if (linkEl.hasClass("external-link")) { const rect = linkEl.getBoundingClientRect(); this.showPreview(linkEl, rect, doc); } }); } /** * Clean up any remaining previews when plugin is disabled */ onunload() { this.activeLinks.forEach((previewEl, linkId) => { previewEl.remove(); }); this.activeLinks.clear(); } /** * Creates and shows a preview window for a link element * @param linkEl - The link element for which to create a preview * @param rect - The bounding rectangle of the link element */ showPreview(linkEl, rect, doc) { const url = linkEl.getAttribute("href"); if (!url) return; const linkId = `preview-${url}`; if (this.activeLinks.has(linkId)) return; let hideTimeout; const win = doc.defaultView; if (!win) return; const handleLinkLeave = () => { hideTimeout = win.setTimeout(cleanupPreview, 300); }; const handlePreviewEnter = () => { if (hideTimeout) { win.clearTimeout(hideTimeout); } }; const handlePreviewLeave = () => { cleanupPreview(); }; const cleanupPreview = () => { const previewEl = this.activeLinks.get(linkId); if (previewEl) { previewEl.remove(); this.activeLinks.delete(linkId); } linkEl.removeEventListener("mouseleave", handleLinkLeave); }; setTimeout(() => { if (this.activeLinks.has(linkId)) return; const hoverEl = this.createPreviewElement(rect); this.activeLinks.set(linkId, hoverEl); const loadingEl = hoverEl.createDiv({ cls: "preview-loading" }); loadingEl.setText("Loading preview..."); const iframeWrapper = hoverEl.createDiv({ cls: "preview-iframe-wrapper" }); const iframe = iframeWrapper.createEl("iframe", { attr: { src: url } }); iframe.addEventListener("load", () => { loadingEl.remove(); iframe.style.display = "block"; }); iframe.addEventListener("error", () => { loadingEl.setText("Failed to load preview"); }); linkEl.addEventListener("mouseleave", handleLinkLeave); hoverEl.addEventListener("mouseenter", handlePreviewEnter); hoverEl.addEventListener("mouseleave", handlePreviewLeave); doc.body.appendChild(hoverEl); }, this.settings.previewDelay); } /** * Creates the preview container element with proper positioning * @param rect - The bounding rectangle used for positioning * @returns HTMLElement configured as preview container */ createPreviewElement(rect) { const el = createEl("div", { cls: "hover-popup" }); el.style.cssText = ` position: fixed; left: ${rect.left}px; top: ${rect.bottom + 5}px; width: ${this.settings.maxPreviewWidth}px; height: ${this.settings.maxPreviewHeight}px; `; return el; } async loadSettings() { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); } async saveSettings() { await this.saveData(this.settings); } }; var LinkPreviewSettingTab = class extends import_obsidian.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.plugin = plugin; } display() { const { containerEl } = this; containerEl.empty(); new import_obsidian.Setting(containerEl).setName("Preview delay").setDesc("How long to wait before showing the preview (in milliseconds)").addText((text) => text.setPlaceholder("300").setValue(String(this.plugin.settings.previewDelay)).onChange(async (value) => { this.plugin.settings.previewDelay = Number(value); await this.plugin.saveSettings(); })); new import_obsidian.Setting(containerEl).setName("Maximum preview height").setDesc("Maximum height of the preview window (in pixels)").addText((text) => text.setPlaceholder("300").setValue(String(this.plugin.settings.maxPreviewHeight)).onChange(async (value) => { this.plugin.settings.maxPreviewHeight = Number(value); await this.plugin.saveSettings(); })); new import_obsidian.Setting(containerEl).setName("Maximum preview width").setDesc("Maximum width of the preview window (in pixels)").addText((text) => text.setPlaceholder("400").setValue(String(this.plugin.settings.maxPreviewWidth)).onChange(async (value) => { this.plugin.settings.maxPreviewWidth = Number(value); await this.plugin.saveSettings(); })); } }; /* nosourcemap */