介绍
# Logseq Plugin API
通过 Logseq 的 JavaScript 插件 API 与本地 Logseq 实例进行交互。此技能支持在 Logseq 图谱中进行读取、写入、查询以及自动化工作流。
## 前置条件
**Logseq 必须在本地运行**,并安装有暴露该 API 的插件。标准方式如下:
1. **安装桥接插件**,通过 HTTP 暴露 `logseq` API(例如,通过自定义插件或 localhost 端点) 2. **替代方案**:使用带有 `@logseq/libs` 包的 Node.js 来针对运行的 Logseq 实例编写脚本
该 API 主要设计用于浏览器内插件,因此从外部脚本访问它需要一个桥接/代理。
## 核心 API 命名空间
Logseq 插件 API 组织为以下主要代理:
### `logseq.App` 应用程序级操作:获取应用信息、用户配置、当前图谱、命令、UI 状态、外部链接。
**关键方法:** - `getInfo()` - 获取应用版本和信息 - `getUserConfigs()` - 获取用户偏好(主题、格式、语言等) - `getCurrentGraph()` - 获取当前图谱信息(名称、路径、URL) - `registerCommand(type, opts, action)` - 注册自定义命令 - `pushState(route, params, query)` - 导航到路由
### `logseq.Editor` 块和页面编辑操作:创建、更新、移动、查询内容。
**关键方法:** - `getBlock(uuid)` - 通过 UUID 获取块 - `getCurrentPage()` - 获取当前页面实体 - `getCurrentPageBlocksTree()` - 获取当前页面上的所有块 - `getPageBlocksTree(page)` - 获取特定页面的所有块 - `insertBlock(target, content, opts)` - 插入一个新块 - `updateBlock(uuid, content)` - 更新块内容 - `createPage(pageName, properties, opts)` - 创建一个新页面 - `deletePage(pageName)` - 删除一个页面 - `getPageLinkedReferences(page)` - 获取指向页面的反向链接 - `registerSlashCommand(tag, action)` - 添加自定义斜杠命令
### `logseq.DB` 使用 Datalog 进行数据库查询。
**关键方法:** - `q(query, ...inputs)` - 运行 Datalog 查询 - `datascriptQuery(query, ...inputs)` - 直接 Datascript 查询
### `logseq.UI` UI 操作:消息、对话框、主 UI 可见性。
**关键方法:** - `showMsg(content, status)` - 显示 Toast 通知 - `queryElementById(id)` - 查询 DOM 元素
### `logseq.Git` 当前图谱的 Git 操作。
**关键方法:** - `execCommand(args)` - 执行 git 命令
### `logseq.Assets` 资源管理。
**关键方法:** - `listFilesOfCurrentGraph(path)` - 列出图谱中的文件
## 常见工作流
### 读取内容
```javascript // Get current page const page = await logseq.Editor.getCurrentPage();
// Get all blocks on a page const blocks = await logseq.Editor.getPageBlocksTree('Daily Notes');
// Get a specific block const block = await logseq.Editor.getBlock('block-uuid-here');
// Query with Datalog const results = await logseq.DB.q(` [:find (pull ?b [*]) :where [?b :block/marker "TODO"]] `); ```
### 写入内容
```javascript // Create a new page await logseq.Editor.createPage('Project Notes', { tags: 'project', status: 'active' }, { redirect: false });
// Insert a block const block = await logseq.Editor.insertBlock( 'target-block-uuid', '- New task item', { before: false, sibling: true } );
// Update a block await logseq.Editor.updateBlock('block-uuid', 'Updated content');
// Batch insert multiple blocks const blocks = [ { content: 'First item' }, { content: 'Second item', children: [ { content: 'Nested item' } ]} ]; await logseq.Editor.insertBatchBlock('parent-uuid', blocks, { sibling: false }); ```
### 任务管理
```javascript // Find all TODO items const todos = await logseq.DB.q(` [:find (pull ?b [*]) :where [?b :block/marker ?marker] [(contains? #{"TODO" "DOING"} ?marker)]] `);
// Mark task as DONE await logseq.Editor.updateBlock('task-uuid', 'DONE Task content');
// Get tasks on current page const page = await logseq.Editor.getCurrentPage(); const blocks = await logseq.Editor.getPageBlocksTree(page.name); const tasks = blocks.filter(b => b.marker === 'TODO' || b.marker === 'DOING'); ```
### 导航与 UI
```javascript // Navigate to a page logseq.App.pushState('page', { name: 'Project Notes' });
// Show notification logseq.UI.showMsg('✅ Task completed!', 'success');
// Get app config const configs = await logseq.App.getUserConfigs(); console.log('Theme:', configs.preferredThemeMode); console.log('Format:', configs.preferredFormat); ```
## 实现方案
由于 Logseq 的插件 API 基于浏览器,您有几种选择:
### 方案 1:桥接插件
创建一个最小的 Logseq 插件,通过 HTTP 暴露 API 调用:
```javascript // In Logseq plugin (index.js) logseq.ready(() => { // Expose API endpoints logseq.provideModel({ async handleAPICall({ method, args }) { return await logseq.Editor[method](...args); } }); });
// Then call from external script via HTTP POST ```
### 方案 2:使用 @logseq/libs 的 Node.js 脚本
对于自动化脚本,请使用 `@logseq/libs` 包:
```bash npm install @logseq/libs ```
**注意:** 这需要一个正在运行的 Logseq 实例以及正确的连接设置。
### 方案 3:直接插件开发
开发一个完整的 Logseq 插件,参考以下插件示例: https://github.com/logseq/logseq-plugin-samples
## API 参考
有关完整的 API 文档,请参阅: - **API 文档**: https://logseq.github.io/plugins/ - **插件示例**: https://github.com/logseq/logseq-plugin-samples - **类型定义**: `references/api-types.md`(从 `@logseq/libs` 中提取)
## 关键数据结构
### BlockEntity ```typescript { id: number, // Entity ID uuid: string, // Block UUID content: string, // Block content format: 'markdown' | 'org', page: { id: number }, // Parent page parent: { id: number }, // Parent block left: { id: number }, // Previous sibling properties: {}, // Block properties marker?: string, // TODO/DOING/DONE children?: [] // Child blocks } ```
### PageEntity ```typescript { id: number, uuid: string, name: string, // Page name (lowercase) originalName: string, // Original case 'journal?': boolean, properties: {}, journalDay?: number, // YYYYMMDD for journals } ```
## 提示与最佳实践
1. **始终检查 null**:如果实体不存在,API 方法可能会返回 `null` 2. **优先使用 UUID 而非 ID**:块的 UUID 是稳定的,实体 ID 可能会发生变化 3. **批量操作**:使用 `insertBatchBlock` 进行多次插入 4. **高效查询**:Datalog 查询很强大,但在大型图谱上可能会很慢 5. **属性是对象**:使用 `block.properties.propertyName` 访问 6. **格式很重要**:请尊重用户的首选格式(markdown 与 org-mode) 7. **全程异步**:所有 API 调用都返回 Promises
## 常见陷阱
- **页面名称为小写**:查询时,请使用小写的页面名称 - **日记页面**:使用 `journalDay` 格式(YYYYMMDD)而不是日期字符串 - **块层级**:插入时请遵守父子关系 - **格式差异**:Markdown 使用 `-` 作为项目符号,Org 使用 `*` - **属性语法**:在 markdown(`prop::`)和 org(`:PROPERTIES:`)之间有所不同