"use strict"; 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); // src/main.ts var main_exports = {}; __export(main_exports, { createLinkEl: () => createLinkEl, default: () => MultiVaultLinksPlugin, openVaultUri: () => openVaultUri }); module.exports = __toCommonJS(main_exports); var import_obsidian2 = require("obsidian"); // src/parse.ts var LINK_RE = /\[\[([^\]]+?)\]\]/g; var VAULT_RE = /^\s*([^#/|:]+?)\s*:\s*([\s\S]+)$/; function parseInner(inner) { const m = VAULT_RE.exec(inner); if (!m) return null; const vault = m[1].trim(); let rest = m[2]; let alias = null; const pipe = rest.indexOf("|"); if (pipe !== -1) { alias = rest.slice(pipe + 1).trim(); rest = rest.slice(0, pipe); } const hash = rest.indexOf("#"); let file; let subpath; if (hash !== -1) { file = rest.slice(0, hash).trim(); subpath = rest.slice(hash).trim(); } else { file = rest.trim(); subpath = ""; } if (!vault || !file) return null; const display = `${vault}: ${file}${subpath}`; return { vault, file, subpath, alias, display }; } function findVaultLinks(text) { const out = []; LINK_RE.lastIndex = 0; let m; while ((m = LINK_RE.exec(text)) !== null) { const parsed = parseInner(m[1]); if (!parsed) continue; out.push({ ...parsed, raw: m[0], start: m.index, end: m.index + m[0].length }); } return out; } function parseVaultTarget(target) { return parseInner(target); } function buildObsidianUri(link) { const vault = encodeURIComponent(link.vault); const file = encodeURIComponent(`${link.file}${link.subpath}`); return `obsidian://open?vault=${vault}&file=${file}`; } // src/livePreview.ts var import_view = require("@codemirror/view"); var import_state = require("@codemirror/state"); var import_obsidian = require("obsidian"); var VaultLinkWidget = class extends import_view.WidgetType { constructor(link) { super(); this.link = link; } eq(other) { return other.link.raw === this.link.raw; } toDOM() { const a = document.createElement("a"); a.className = "multi-vault-link cm-multi-vault-link"; const uri = buildObsidianUri(this.link); a.href = uri; a.setAttribute("aria-label", `${this.link.vault} \u2192 ${this.link.file}${this.link.subpath}`); a.textContent = this.link.display; a.addEventListener("click", (evt) => { evt.preventDefault(); evt.stopPropagation(); window.open(uri); }); return a; } ignoreEvent() { return true; } }; function selectionTouches(view, from, to) { return view.state.selection.ranges.some((r) => r.from <= to && r.to >= from); } function buildDecorations(view) { const builder = new import_state.RangeSetBuilder(); const livePreview = view.state.field(import_obsidian.editorLivePreviewField); for (const { from, to } of view.visibleRanges) { const text = view.state.doc.sliceString(from, to); for (const link of findVaultLinks(text)) { const start = from + link.start; const end = from + link.end; if (!livePreview || selectionTouches(view, start, end)) { builder.add(start, end, import_view.Decoration.mark({ class: "cm-multi-vault-source" })); continue; } builder.add( start, end, import_view.Decoration.replace({ widget: new VaultLinkWidget(link) }) ); } } return builder.finish(); } var multiVaultLivePreview = import_view.ViewPlugin.fromClass( class { constructor(view) { this.decorations = buildDecorations(view); } update(update) { const modeChanged = update.startState.field(import_obsidian.editorLivePreviewField) !== update.state.field(import_obsidian.editorLivePreviewField); if (update.docChanged || update.viewportChanged || update.selectionSet || modeChanged) { this.decorations = buildDecorations(update.view); } } }, { decorations: (v) => v.decorations } ); // src/main.ts var SKIP_TAGS = /* @__PURE__ */ new Set(["CODE", "PRE", "A"]); function isInsideSkipped(node) { let el = node.parentElement; while (el) { if (SKIP_TAGS.has(el.tagName)) return true; el = el.parentElement; } return false; } function openVaultUri(uri, win = window) { win.open(uri); } function attachOpenHandler(a, uri) { a.addEventListener("click", (evt) => { evt.preventDefault(); evt.stopPropagation(); openVaultUri(uri, a.ownerDocument.defaultView ?? window); }); } function buildAnchor(doc, link, display) { const a = doc.createElement("a"); a.addClass("multi-vault-link"); const uri = buildObsidianUri(link); a.setAttribute("href", uri); a.setAttribute("aria-label", `${link.vault} \u2192 ${link.file}${link.subpath}`); a.textContent = display; attachOpenHandler(a, uri); return a; } function createLinkEl(doc, link) { return buildAnchor(doc, link, link.display); } function rewriteInternalLinks(el) { el.querySelectorAll("a.internal-link").forEach((a) => { const target = a.getAttribute("data-href") ?? a.getAttribute("href") ?? ""; const link = parseVaultTarget(target); if (!link) return; a.replaceWith(buildAnchor(a.ownerDocument, link, link.display)); }); } function rewriteTextNode(node) { const text = node.nodeValue ?? ""; const links = findVaultLinks(text); if (links.length === 0) return; const doc = node.ownerDocument; const frag = doc.createDocumentFragment(); let cursor = 0; for (const link of links) { if (link.start > cursor) { frag.appendChild(doc.createTextNode(text.slice(cursor, link.start))); } frag.appendChild(createLinkEl(doc, link)); cursor = link.end; } if (cursor < text.length) { frag.appendChild(doc.createTextNode(text.slice(cursor))); } node.replaceWith(frag); } var MultiVaultLinksPlugin = class extends import_obsidian2.Plugin { async onload() { this.registerMarkdownPostProcessor((el) => { rewriteInternalLinks(el); const walker = el.ownerDocument.createTreeWalker(el, NodeFilter.SHOW_TEXT); const targets = []; let n; while (n = walker.nextNode()) { const t = n; if (!t.nodeValue || !t.nodeValue.includes("[[")) continue; if (isInsideSkipped(t)) continue; targets.push(t); } targets.forEach(rewriteTextNode); }); this.registerEditorExtension(multiVaultLivePreview); this.patchOpenLinkText(); } patchOpenLinkText() { const ws = this.app.workspace; const original = ws.openLinkText.bind(ws); ws.openLinkText = (linktext, sourcePath, newLeaf, viewState) => { const link = parseVaultTarget(linktext); if (link) { openVaultUri(buildObsidianUri(link)); return Promise.resolve(); } return original(linktext, sourcePath, newLeaf, viewState); }; this.register(() => { ws.openLinkText = original; }); } };