API 参考
核心模块
App
主应用实例,通过 this.app 访问。
typescript
// 获取当前活动文件
const file = app.workspace.getActiveFile();
// 获取仓库信息
const vault = app.vault;
// 获取工作区
const workspace = app.workspace;
// 获取元数据缓存
const metadataCache = app.metadataCache;Plugin
插件基类。
typescript
class MyPlugin extends Plugin {
async onload() {
// 插件入口
}
onunload() {
// 清理资源
}
// 数据持久化
async loadData(): Promise<T>
async saveData(data: T): Promise<void>
// 注册方法
addCommand(command: Command): Command
addRibbonIcon(icon: string, title: string, callback: (evt: MouseEvent) => any): HTMLElement
addStatusBarItem(): HTMLElement
addSettingTab(settingTab: PluginSettingTab): void
registerView(type: string, viewCreator: ViewCreator): void
registerEvent(eventRef: EventRef): void
registerDomEvent(el: HTMLElement, type: string, callback: (evt: Event) => any): void
registerInterval(id: number): void
}Workspace
工作区管理。
typescript
const workspace = app.workspace;
// 获取活动视图
const view = workspace.getActiveViewOfType(MarkdownView);
// 获取活动编辑器
const editor = workspace.activeEditor?.editor;
// 打开文件
await workspace.openLinkText('note-name', '', true);
// 获取叶子
const leaf = workspace.getLeaf(false);
const leaf = workspace.getLeaf(true); // 新建标签页
// 更新视图
await leaf.setViewState({
type: 'markdown',
state: { file: 'path/to/file.md' }
});
// 事件
workspace.on('file-open', (file) => { });
workspace.on('active-leaf-change', (leaf) => { });
workspace.on('layout-change', () => { });Vault
文件系统操作。
typescript
const vault = app.vault;
// 获取文件
const file = vault.getAbstractFileByPath('path/to/file.md');
const folder = vault.getAbstractFileByPath('path/to/folder');
// 列出文件
const files = vault.getFiles();
const mdFiles = vault.getMarkdownFiles();
// 读取文件
const content = await vault.read(file);
const data = await vault.readBinary(file);
// 写入文件
await vault.modify(file, 'new content');
await vault.append(file, '\nmore content');
// 创建文件
await vault.create('path/new.md', 'content');
await vault.createFolder('new-folder');
// 删除文件
await vault.trash(file, true); // 移到回收站
await vault.delete(file); // 永久删除
// 重命名/移动
await vault.rename(file, 'new/path.md');
// 事件
vault.on('create', (file) => { });
vault.on('modify', (file) => { });
vault.on('delete', (file) => { });
vault.on('rename', (file, oldPath) => { });MetadataCache
元数据缓存。
typescript
const cache = app.metadataCache;
// 获取文件元数据
const metadata = cache.getFileCache(file);
// 访问 frontmatter
const frontmatter = metadata?.frontmatter;
// 访问链接
const links = metadata?.links;
const embeds = metadata?.embeds;
// 访问标题
const headings = metadata?.headings;
// 获取反向链接
const backlinks = cache.getBacklinksForFile(file);
// 解析链接
const linkInfo = cache.getFirstLinkpathDest('[[note-name]]', '');
// 事件
cache.on('changed', (file) => { });
cache.on('resolved', () => { });Editor
编辑器操作。
typescript
const editor = workspace.activeEditor?.editor;
// 获取内容
const content = editor.getValue();
const line = editor.getLine(lineNumber);
// 设置内容
editor.setValue('new content');
editor.replaceRange('text', { line: 0, ch: 0 }, { line: 0, ch: 5 });
// 光标操作
const cursor = editor.getCursor();
const selections = editor.listSelections();
editor.setCursor({ line: 0, ch: 0 });
editor.setSelection({ line: 0, ch: 0 }, { line: 1, ch: 0 });
// 选中文本
const selected = editor.getSelection();
editor.replaceSelection('new text');
// 滚动
editor.scrollIntoView({ line: 10, ch: 0 });
editor.scrollTo(0, 100);
// 行操作
const count = editor.lineCount();
const pos = editor.posToOffset({ line: 0, ch: 0 });
const coords = editor.offsetToPos(0);
// 折叠
editor.fold(lineNumber);
editor.unfold(lineNumber);
editor.toggleFold(lineNumber);TFile / TFolder
文件和文件夹类型。
typescript
// TFile 属性
file.path // 完整路径
file.name // 文件名(含扩展名)
file.basename // 文件名(不含扩展名)
file.extension // 扩展名
file.parent // 父文件夹
file.stat // 文件状态 { mtime, ctime, size }
// TFolder 属性
folder.path // 完整路径
folder.name // 文件夹名
folder.parent // 父文件夹
folder.children // 子文件/文件夹
// 类型检查
if (file instanceof TFile) { }
if (folder instanceof TFolder) { }Commands
命令定义。
typescript
interface Command {
id: string;
name: string;
icon?: string;
editorCallback?: (editor: Editor, view: MarkdownView) => void;
editorCheckCallback?: (checking: boolean, editor: Editor, view: MarkdownView) => boolean | void;
callback?: () => void;
checkCallback?: (checking: boolean) => boolean | void;
}
// 注册命令
this.addCommand({
id: 'my-command',
name: 'My Command',
editorCallback: (editor, view) => {
editor.replaceSelection('Hello!');
}
});Settings
设置面板。
typescript
class MySettingTab extends PluginSettingTab {
display(): void {
const { containerEl } = this;
containerEl.empty();
// 文本设置
new Setting(containerEl)
.setName('Name')
.setDesc('Description')
.addText(text => text
.setPlaceholder('Placeholder')
.setValue(value)
.onChange(async (value) => { }));
// 开关设置
new Setting(containerEl)
.addToggle(toggle => toggle
.setValue(bool)
.onChange(async (value) => { }));
// 下拉选择
new Setting(containerEl)
.addDropdown(dropdown => dropdown
.addOption('key', 'Label')
.setValue(value)
.onChange(async (value) => { }));
// 滑块
new Setting(containerEl)
.addSlider(slider => slider
.setLimits(0, 100, 1)
.setValue(value)
.setDynamicTooltip()
.onChange(async (value) => { }));
// 按钮
new Setting(containerEl)
.addButton(button => button
.setButtonText('Click me')
.setCta()
.onClick(() => { }));
}
}Notice
通知消息。
typescript
import { Notice } from 'obsidian';
// 基本用法
new Notice('Message');
// 设置持续时间(毫秒)
new Notice('Message', 5000);
// 无限持续时间
new Notice('Message', 0);Modal
模态框。
typescript
import { App, Modal } from 'obsidian';
class MyModal extends Modal {
constructor(app: App) {
super(app);
}
onOpen() {
const { contentEl } = this;
contentEl.createEl('h1', { text: 'Title' });
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
}
// 打开模态框
new MyModal(this.app).open();FuzzySuggestModal
模糊搜索模态框。
typescript
import { App, FuzzySuggestModal } from 'obsidian';
class MySuggestModal extends FuzzySuggestModal<string> {
items: string[];
constructor(app: App, items: string[]) {
super(app);
this.items = items;
}
getItems(): string[] {
return this.items;
}
getItemText(item: string): string {
return item;
}
onChooseItem(item: string, evt: MouseEvent | KeyboardEvent): void {
console.log('Selected:', item);
}
}常用类型
typescript
// 文件类型
type TAbstractFile = TFile | TFolder;
// 编辑器位置
interface EditorPosition {
line: number;
ch: number;
}
// 编辑器范围
interface EditorRange {
from: EditorPosition;
to: EditorPosition;
}
// 视图状态
interface ViewState {
type: string;
state: Record<string, any>;
}
// 工作区叶子
class WorkspaceLeaf {
view: View;
tabHeaderEl: HTMLElement;
getViewState(): ViewState;
setViewState(viewState: ViewState): Promise<void>;
openFile(file: TFile): Promise<void>;
}更多资源
Events
事件系统是插件与 Obsidian 交互的核心机制。
事件监听
typescript
// 在插件中监听事件
this.registerEvent(
this.app.vault.on('create', (file) => {
console.log('文件创建:', file.path);
})
);
// 监听工作区事件
this.registerEvent(
this.app.workspace.on('file-open', (file) => {
if (file) {
console.log('打开文件:', file.path);
}
})
);registerEvent
使用 this.registerEvent() 而非 app.vault.on(),这样插件卸载时会自动取消监听,避免内存泄漏。
常用 Vault 事件
| 事件 | 参数 | 说明 |
|---|---|---|
create | (file: TAbstractFile) | 文件或文件夹创建 |
modify | (file: TAbstractFile) | 文件内容修改 |
delete | (file: TAbstractFile) | 文件或文件夹删除 |
rename | (file: TAbstractFile, oldPath: string) | 文件或文件夹重命名 |
常用 Workspace 事件
| 事件 | 参数 | 说明 |
|---|---|---|
file-open | (file: TFile | null) | 活动文件变更 |
active-leaf-change | (leaf: WorkspaceLeaf | null) | 活动叶子变更 |
layout-change | 无 | 工作区布局变化 |
resize | 无 | 窗口大小变化 |
quick-open | 无 | 快速切换打开 |
自定义事件
typescript
// 触发自定义事件
this.app.workspace.trigger('my-plugin:action', { data: 'value' });
// 监听自定义事件
this.registerEvent(
this.app.workspace.on('my-plugin:action' as any, (data) => {
console.log('收到自定义事件:', data);
})
);FileManager
文件管理器,提供高级文件操作。
typescript
const fileManager = app.fileManager;
// 获取笔记的新链接文本(处理别名等)
const linkText = fileManager.generateMarkdownLink(
file, // 目标文件
sourcePath, // 来源文件路径
'#heading', // 可选子路径
'别名' // 可选别名
);
// 保存前端元数据
await fileManager.processFrontMatter(file, (frontmatter) => {
frontmatter.tags = ['updated'];
frontmatter.lastModified = Date.now();
});
// 重命名并更新链接
await fileManager.renameFile(file, 'new/path.md');processFrontMatter
processFrontMatter 是安全修改 frontmatter 的推荐方式,它会自动处理 YAML 序列化:
typescript
// 添加标签
await app.fileManager.processFrontMatter(file, (fm) => {
if (!fm.tags) fm.tags = [];
fm.tags.push('new-tag');
});
// 修改属性
await app.fileManager.processFrontMatter(file, (fm) => {
fm.status = 'done';
fm.completedAt = new Date().toISOString();
});
// 删除属性
await app.fileManager.processFrontMatter(file, (fm) => {
delete fm.temporaryField;
});注意
processFrontMather 会在文件内容中重新生成 frontmatter 块,可能改变格式(如引号风格、缩进)。如果需要精确控制格式,请使用 vault.modify() 直接修改文件内容。
RequestUrl
HTTP 请求 API,用于与外部服务交互。
typescript
import { requestUrl, RequestUrlParam } from 'obsidian';
// GET 请求
const response = await requestUrl('https://api.example.com/data');
console.log(response.json);
// POST 请求
const result = await requestUrl({
url: 'https://api.example.com/submit',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token'
},
body: JSON.stringify({ key: 'value' })
});
// 带超时的请求
try {
const data = await requestUrl({
url: 'https://api.example.com/data',
method: 'GET',
throw: false // 不自动抛出 HTTP 错误
});
if (data.status === 200) {
console.log(data.json);
}
} catch (error) {
console.error('请求失败:', error);
}CORS 限制
Obsidian 的 requestUrl 不受浏览器 CORS 限制,可以直接请求任何外部 API。这是插件开发相对于普通 Web 应用的优势之一。
Editor Extensions
编辑器扩展 API,用于自定义编辑器行为。
状态栏
typescript
// 添加状态栏项
const statusBarItem = this.addStatusBarItem();
statusBarItem.setText('就绪');
statusBarItem.addClass('my-plugin-status');
// 更新状态
function updateStatus(text: string) {
statusBarItem.setText(text);
}功能区图标
typescript
// 添加功能区图标
const ribbonIcon = this.addRibbonIcon(
'star', // 图标名称
'My Plugin', // 提示文本
(evt: MouseEvent) => {
// 点击回调
new Notice('功能已触发');
}
);
// 自定义图标样式
ribbonIcon.addClass('my-plugin-ribbon');命令面板
typescript
// 注册命令
this.addCommand({
id: 'format-note',
name: '格式化当前笔记',
editorCallback: (editor, view) => {
const content = editor.getValue();
const formatted = formatContent(content);
editor.setValue(formatted);
}
});
// 带条件的命令
this.addCommand({
id: 'insert-date',
name: '插入日期',
checkCallback: (checking) => {
const file = app.workspace.getActiveFile();
if (!file) return false;
if (checking) return true;
// 执行操作
app.workspace.activeEditor?.editor.replaceSelection(
new Date().toLocaleDateString()
);
}
});View
自定义视图 API。
typescript
import { ItemView, WorkspaceLeaf } from 'obsidian';
// 定义视图类型常量
const VIEW_TYPE_EXAMPLE = 'example-view';
class ExampleView extends ItemView {
constructor(leaf: WorkspaceLeaf) {
super(leaf);
}
getViewType(): string {
return VIEW_TYPE_EXAMPLE;
}
getDisplayText(): string {
return '示例视图';
}
getIcon(): string {
return 'star';
}
async onOpen() {
const container = this.containerEl.children[1];
container.empty();
container.createEl('h1', { text: '示例视图' });
container.createEl('p', { text: '这是一个自定义视图。' });
}
async onClose() {
// 清理资源
}
}
// 注册视图
this.registerView(VIEW_TYPE_EXAMPLE, (leaf) => new ExampleView(leaf));
// 打开视图
async function openExampleView() {
const leaf = app.workspace.getLeaf(false);
await leaf.setViewState({
type: VIEW_TYPE_EXAMPLE,
active: true,
});
}Plugin Settings
插件设置的完整模式。
typescript
// 定义设置接口
interface MyPluginSettings {
apiKey: string;
autoSync: boolean;
syncInterval: number;
folders: string[];
}
// 默认设置
const DEFAULT_SETTINGS: MyPluginSettings = {
apiKey: '',
autoSync: true,
syncInterval: 60,
folders: [],
};
// 在插件中加载/保存设置
class MyPlugin extends Plugin {
settings: MyPluginSettings;
async onload() {
await this.loadSettings();
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
}
// 设置面板
class MySettingTab extends PluginSettingTab {
plugin: MyPlugin;
display(): void {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl('h2', { text: '插件设置' });
// API Key
new Setting(containerEl)
.setName('API Key')
.setDesc('输入你的 API 密钥')
.addText((text) =>
text
.setPlaceholder('sk-xxx')
.setValue(this.plugin.settings.apiKey)
.onChange(async (value) => {
this.plugin.settings.apiKey = value;
await this.plugin.saveSettings();
})
);
// 自动同步开关
new Setting(containerEl)
.setName('自动同步')
.setDesc('启用后定时自动同步')
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.autoSync)
.onChange(async (value) => {
this.plugin.settings.autoSync = value;
await this.plugin.saveSettings();
})
);
// 同步间隔
new Setting(containerEl)
.setName('同步间隔')
.setDesc('自动同步的间隔时间(分钟)')
.addSlider((slider) =>
slider
.setLimits(5, 120, 5)
.setValue(this.plugin.settings.syncInterval)
.setDynamicTooltip()
.onChange(async (value) => {
this.plugin.settings.syncInterval = value;
await this.plugin.saveSettings();
})
);
// 文件夹选择
new Setting(containerEl)
.setName('同步文件夹')
.setDesc('选择要同步的文件夹')
.addDropdown((dropdown) => {
const folders = app.vault.getAllFolders();
folders.forEach((folder) => {
dropdown.addOption(folder.path, folder.name || '/');
});
dropdown.onChange(async (value) => {
if (!this.plugin.settings.folders.includes(value)) {
this.plugin.settings.folders.push(value);
await this.plugin.saveSettings();
}
});
});
}
}
// 注册设置面板
this.addSettingTab(new MySettingTab(this.app, this));常用图标
Obsidian 内置的 Lucide 图标可在 addRibbonIcon、addCommand 等处使用:
| 图标名 | 用途 |
|---|---|
document | 文档/笔记 |
folder | 文件夹 |
search | 搜索 |
star | 收藏/标记 |
gear | 设置 |
plus | 新建/添加 |
trash | 删除 |
pencil | 编辑 |
link | 链接 |
image | 图片 |
code | 代码 |
checkmark | 完成/确认 |
cross | 关闭/取消 |
refresh | 刷新 |
download | 下载 |
upload | 上传 |
clipboard | 剪贴板 |
calendar | 日历 |
clock | 时间 |
tag | 标签 |
完整图标列表参见 Lucide Icons。