86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
import { App, Menu, Platform, TFile, View, WorkspaceLeaf, normalizePath } from "obsidian";
|
|
|
|
export function menu(
|
|
ev: MouseEvent,
|
|
items: Array<{ title: string; icon?: string; onClick: () => void }>,
|
|
): void {
|
|
const m = new Menu();
|
|
for (const it of items) {
|
|
m.addItem((i) => {
|
|
i.setTitle(it.title);
|
|
if (it.icon) i.setIcon(it.icon);
|
|
i.onClick(it.onClick);
|
|
});
|
|
}
|
|
m.showAtMouseEvent(ev);
|
|
}
|
|
|
|
export async function openMarkdown(
|
|
app: App,
|
|
path: string,
|
|
leaf?: WorkspaceLeaf,
|
|
): Promise<void> {
|
|
const p = normalizePath(path);
|
|
const f = app.vault.getAbstractFileByPath(p);
|
|
if (!(f instanceof TFile)) return;
|
|
if (Platform.isMobile) {
|
|
const target = leaf ?? app.workspace.getLeaf(false);
|
|
await target.openFile(f);
|
|
return;
|
|
}
|
|
const existing = app.workspace.getLeavesOfType("markdown");
|
|
if (existing.length > 0) {
|
|
const target = existing[existing.length - 1];
|
|
await target.openFile(f);
|
|
app.workspace.revealLeaf(target);
|
|
} else {
|
|
const target = app.workspace.getLeaf("split", "vertical");
|
|
await target.openFile(f);
|
|
}
|
|
}
|
|
|
|
export interface BreadcrumbSegment {
|
|
label: string;
|
|
onClick?: () => void;
|
|
}
|
|
|
|
function renderBreadcrumbInto(wrap: HTMLElement, segments: BreadcrumbSegment[]): void {
|
|
segments.forEach((seg, i) => {
|
|
if (i > 0) wrap.createSpan({ cls: "pk-breadcrumb-sep", text: " > " });
|
|
if (seg.onClick) {
|
|
const a = wrap.createSpan({ cls: "pk-breadcrumb-link", text: seg.label });
|
|
a.addEventListener("click", seg.onClick);
|
|
} else {
|
|
wrap.createSpan({ cls: "pk-breadcrumb-current", text: seg.label });
|
|
}
|
|
});
|
|
}
|
|
|
|
export function breadcrumb(parent: HTMLElement, segments: BreadcrumbSegment[]): HTMLElement {
|
|
const wrap = parent.createDiv({ cls: "pk-breadcrumb" });
|
|
renderBreadcrumbInto(wrap, segments);
|
|
return wrap;
|
|
}
|
|
|
|
export function injectMobileBreadcrumb(
|
|
view: View & { contentEl?: HTMLElement },
|
|
segments: BreadcrumbSegment[],
|
|
): void {
|
|
const root = view.contentEl ?? view.containerEl.querySelector(".view-content");
|
|
if (!root) return;
|
|
root.querySelectorAll(".pk-mobile-breadcrumb").forEach((el) => el.remove());
|
|
if (segments.length === 0) return;
|
|
const target =
|
|
root.querySelector<HTMLElement>(".markdown-source-view .cm-sizer") ??
|
|
root.querySelector<HTMLElement>(".markdown-reading-view .markdown-preview-sizer");
|
|
if (!target) return;
|
|
const wrap = document.createElement("div");
|
|
wrap.className = "pk-breadcrumb pk-mobile-breadcrumb";
|
|
target.prepend(wrap);
|
|
renderBreadcrumbInto(wrap, segments);
|
|
}
|
|
|
|
export function emptyState(parent: HTMLElement, text: string): HTMLElement {
|
|
return parent.createDiv({ cls: "pk-empty", text });
|
|
}
|