Skip to content

开发入门

概述

Obsidian 支持通过插件和主题进行扩展开发。本章节将介绍开发环境的搭建和基础知识。

开发环境准备

必需工具

  • Node.js:v16 或更高版本
  • npmpnpm:包管理器
  • 代码编辑器:推荐 VS Code
  • Git:版本控制

安装 Node.js

bash
# macOS/Linux (使用 nvm)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
nvm install 18
nvm use 18

# Windows (使用 winget)
winget install OpenJS.NodeJS.LTS

# 验证安装
node --version
npm --version

推荐的 VS Code 插件

插件名称用途
ESLint代码检查
Prettier代码格式化
TypeScript and JavaScript语言支持
GitLensGit 增强

创建插件项目

使用模板

推荐使用官方模板快速创建项目:

bash
# 克隆模板
git clone https://github.com/obsidianmd/obsidian-sample-plugin my-plugin
cd my-plugin

# 安装依赖
npm install

# 或使用 degit
npx degit obsidianmd/obsidian-sample-plugin my-plugin

项目结构

text
my-plugin/
├── main.ts              # 插件入口文件
├── manifest.json        # 插件清单
├── styles.css          # 插件样式(可选)
├── tsconfig.json       # TypeScript 配置
├── esbuild.config.mjs  # 构建配置
├── package.json        # 项目配置
└── .github/            # GitHub Actions 配置

manifest.json

json
{
  "id": "my-plugin",
  "name": "My Plugin",
  "version": "1.0.0",
  "minAppVersion": "1.0.0",
  "description": "A sample Obsidian plugin",
  "author": "Your Name",
  "authorUrl": "https://github.com/yourusername",
  "isDesktopOnly": false
}

main.ts 基本结构

typescript
import { App, Plugin, PluginSettingTab, Setting } from 'obsidian';

// 定义设置接口
interface MyPluginSettings {
  mySetting: string;
}

// 默认设置
const DEFAULT_SETTINGS: MyPluginSettings = {
  mySetting: 'default value'
};

// 插件主类
export default class MyPlugin extends Plugin {
  settings: MyPluginSettings;

  async onload() {
    await this.loadSettings();

    // 注册命令
    this.addCommand({
      id: 'hello-command',
      name: 'Say Hello',
      callback: () => {
        console.log('Hello from my plugin!');
      }
    });

    // 添加设置面板
    this.addSettingTab(new MySettingTab(this.app, this));
  }

  onunload() {
    console.log('Plugin unloaded');
  }

  async loadSettings() {
    this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
  }

  async saveSettings() {
    await this.saveData(this.settings);
  }
}

// 设置面板
class MySettingTab extends PluginSettingTab {
  plugin: MyPlugin;

  constructor(app: App, plugin: MyPlugin) {
    super(app, plugin);
    this.plugin = plugin;
  }

  display(): void {
    const { containerEl } = this;
    containerEl.empty();

    new Setting(containerEl)
      .setName('Setting name')
      .setDesc('Setting description')
      .addText(text => text
        .setValue(this.plugin.settings.mySetting)
        .onChange(async (value) => {
          this.plugin.settings.mySetting = value;
          await this.plugin.saveSettings();
        }));
  }
}

开发流程

本地开发

  1. 编译插件

    bash
    npm run dev
  2. 链接到 Obsidian

    bash
    # macOS/Linux
    ln -s /path/to/my-plugin /path/to/vault/.obsidian/plugins/my-plugin
    
    # Windows (PowerShell)
    New-Item -ItemType SymbolicLink -Path "C:\path\to\vault\.obsidian\plugins\my-plugin" -Target "C:\path\to\my-plugin"
  3. 在 Obsidian 中启用插件

    • 打开设置 → 第三方插件
    • 刷新插件列表
    • 找到并启用你的插件

热重载

修改代码后,需要重新加载插件:

  • 方法一:禁用再启用插件
  • 方法二:使用「Hot Reload」插件自动重载
  • 方法三:Ctrl/Cmd + R 重新加载 Obsidian

调试

打开开发者工具:

  • macOSCmd + Option + I
  • Windows/LinuxCtrl + Shift + I
typescript
// 使用 console.log 调试
console.log('Debug info', someVariable);

// 使用 console.error 记录错误
console.error('Something went wrong', error);

发布插件

准备发布

  1. 更新 manifest.json 中的版本号
  2. 构建生产版本
    bash
    npm run build
  3. 确保包含必要文件
    • main.js
    • manifest.json
    • styles.css(如有)

发布到社区

  1. 在 GitHub 创建仓库
  2. 推送代码
  3. 创建 Release,上传构建文件
  4. Fork obsidian-releases 仓库
  5. 编辑 community-plugins.json,添加你的插件信息
  6. 提交 Pull Request

GitHub Release 配置

可以使用 GitHub Actions 自动构建:

yaml
# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - '*'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - run: npm ci
      - run: npm run build
      - uses: softprops/action-gh-release@v1
        with:
          files: |
            main.js
            manifest.json
            styles.css

TypeScript 配置

json
// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "inlineSourceMap": true,
    "inlineSources": true,
    "module": "ESNext",
    "target": "ES6",
    "allowJs": true,
    "noImplicitAny": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "isolatedModules": true,
    "strictNullChecks": true,
    "lib": ["DOM", "ES5", "ES6", "ES7"]
  },
  "include": ["**/*.ts"]
}

下一步

Obsidian API 核心 API 速览

理解 Obsidian 插件开发的关键 API,帮助你快速上手。

常用 API 分类

分类核心类/方法用途
插件生命周期onload() / onunload()插件加载和卸载时执行
命令注册this.addCommand()注册命令面板命令
事件监听this.registerEvent()监听 Vault 事件
设置管理this.loadData() / this.saveData()读写插件配置
视图this.addView()注册自定义视图
Ribbonthis.addRibbonIcon()添加侧边栏图标
状态栏this.addStatusBarItem()添加状态栏元素

文件操作 API

typescript
// 读取文件
const content = await this.app.vault.read(file);

// 写入文件
await this.app.vault.modify(file, newContent);

// 创建文件
const newFile = await this.app.vault.create(path, content);

// 删除文件
await this.app.vault.delete(file);

// 获取文件
const file = this.app.vault.getAbstractFileByPath('path/to/note.md');

// 列出文件夹中的文件
const files = this.app.vault.getFiles();
const markdownFiles = this.app.vault.getMarkdownFiles();

编辑器操作 API

typescript
// 获取当前活动编辑器
const activeFile = this.app.workspace.getActiveFile();
const editor = this.app.workspace.activeEditor?.editor;

// 读取选中内容
const selection = editor?.getSelection();

// 替换选中内容
editor?.replaceSelection('替换文本');

// 在光标位置插入内容
editor?.replaceRange('插入内容', editor.getCursor());

// 获取当前行内容
const line = editor?.getLine(editor.getCursor().line);

事件系统

typescript
// 监听文件创建
this.registerEvent(
  this.app.vault.on('create', (file) => {
    console.log('文件创建:', file.path);
  })
);

// 监听文件修改
this.registerEvent(
  this.app.vault.on('modify', (file) => {
    console.log('文件修改:', file.path);
  })
);

// 监听活动文件变化
this.registerEvent(
  this.app.workspace.on('active-leaf-change', (leaf) => {
    console.log('活动视图变化');
  })
);

// 监听布局变化
this.registerEvent(
  this.app.workspace.on('layout-change', () => {
    console.log('布局变化');
  })
);

模态框(Modal)

typescript
// 自定义模态框
class MyModal extends Modal {
  constructor(app: App) {
    super(app);
  }

  onOpen() {
    const { contentEl } = this;
    contentEl.createEl('h2', { text: '我的模态框' });
    
    new Setting(contentEl)
      .setName('输入')
      .addText(text => text.onChange(value => {
        // 处理输入
      }));
    
    new ButtonComponent(contentEl)
      .setButtonText('确定')
      .onClick(() => {
        this.close();
      });
  }

  onClose() {
    const { contentEl } = this;
    contentEl.empty();
  }
}

// 使用
new MyModal(this.app).open();

通知(Notice)

typescript
// 简单通知
new Notice('操作成功!');

// 带超时的通知(5秒)
new Notice('处理中,请稍候...', 5000);

// 错误通知
new Notice('❌ 操作失败,请重试');

常见开发模式

模式一:命令型插件

注册命令,用户通过命令面板触发:

typescript
this.addCommand({
  id: 'format-note',
  name: '格式化当前笔记',
  editorCallback: (editor, view) => {
    const content = editor.getValue();
    const formatted = formatMarkdown(content);
    editor.setValue(formatted);
  }
});

模式二:视图型插件

创建自定义视图,显示特殊内容:

typescript
// 注册视图
this.registerView('my-view', (leaf) => new MyView(leaf));

// 添加命令打开视图
this.addCommand({
  id: 'open-my-view',
  name: '打开自定义视图',
  callback: () => {
    this.app.workspace.detachLeavesOfType('my-view');
    const leaf = this.app.workspace.getRightLeaf(false);
    leaf?.setViewState({ type: 'my-view' });
    this.app.workspace.revealLeaf(leaf!);
  }
});

模式三:自动处理型插件

监听事件,自动执行操作:

typescript
// 自动为新笔记添加 frontmatter
this.registerEvent(
  this.app.vault.on('create', async (file) => {
    if (!(file instanceof TFile) || file.extension !== 'md') return;
    
    const content = await this.app.vault.read(file);
    if (content.startsWith('---')) return; // 已有 frontmatter
    
    const frontmatter = `---
created: ${new Date().toISOString()}
tags: []
---
`;
    await this.app.vault.modify(file, frontmatter + content);
  })
);

开发工具与技巧

推荐开发工具

工具用途安装方式
Hot Reload修改代码后自动重载插件社区插件
Obsidian API TypesTypeScript 类型提示npm install obsidian
esbuild快速打包已在模板中配置

调试技巧

typescript
// 1. 使用 console 输出
console.log('变量值:', variable);
console.table(arrayData);  // 表格形式输出数组

// 2. 使用 Notice 快速反馈
new Notice(`结果: ${result}`);

// 3. 使用 debugger 断点
debugger;  // 代码执行到这里会暂停

// 4. 监控性能
console.time('操作耗时');
// ... 执行代码
console.timeEnd('操作耗时');

开发常见错误

错误原因解决方案
Cannot read property of undefinedAPI 对象未正确获取添加空值检查
插件加载后无效果onload() 中未注册功能检查 onload() 实现
修改代码后无变化未重载插件使用 Hot Reload 或 Ctrl+R
类型错误API 类型定义未安装npm install obsidian
样式不生效CSS 文件未正确引入检查 styles.css 位置

进阶开发指引

掌握了基础知识后,可以深入学习以下方向:

插件发布流程

  1. 代码质量:确保代码清晰、有注释
  2. README 编写:说明插件功能和使用方法
  3. 版本管理:遵循语义化版本号
  4. 提交审核:Fork obsidian-releases 仓库提交 PR

推荐学习资源