212 lines
6.9 KiB
Markdown
212 lines
6.9 KiB
Markdown
# Zotero Org Export Annotations
|
|
|
|
Export PDF and EPUB annotations from Zotero to Org-mode files for use with Emacs, org-roam, and citar.
|
|
|
|
## Features
|
|
|
|
- Export annotations to individual Org files named by citation key
|
|
- Automatic export after Zotero sync completes
|
|
- Export when closing a PDF/EPUB reader tab
|
|
- Configurable output directory
|
|
- Optional attachment of Org files to Zotero items
|
|
|
|
## Requirements
|
|
|
|
- **[Zotero](https://www.zotero.org/) 7.0+**
|
|
- **[Better Notes](https://github.com/windingwind/zotero-better-notes)** plugin — must be installed before this plugin
|
|
- **[Pandoc](https://pandoc.org/)** — for Markdown to Org conversion
|
|
|
|
## Installation
|
|
|
|
1. Install the **Better Notes** plugin first (see its own instructions)
|
|
2. Install **Pandoc** and ensure it is on your `PATH` (or note its full path)
|
|
3. Download the latest `.xpi` file from [Releases](../../releases)
|
|
4. In Zotero, go to **Tools → Add-ons**
|
|
5. Click the gear icon (top-right) and select **Install Add-on From File...**
|
|
6. Select the downloaded `.xpi` file and restart Zotero if prompted
|
|
|
|
## Configuration
|
|
|
|
After installation, open **Tools → Org Export Preferences** to configure:
|
|
|
|
| Preference | Default | Description |
|
|
| ----------------------- | --------- | --------------------------------------------------------------- |
|
|
| Notes Directory | _(empty)_ | Directory where Org files will be saved. Supports `~` for home. |
|
|
| Pandoc Path | `pandoc` | Full path to the pandoc binary if not on `PATH` |
|
|
| Attach Org file to item | `false` | Link exported Org files as Zotero attachments |
|
|
| Auto-export on sync | `true` | Export automatically after Zotero sync completes |
|
|
| Export on tab close | `true` | Export when closing a PDF/EPUB reader tab |
|
|
| Show notifications | `true` | Display a progress notification during export |
|
|
| Debug mode | `false` | Enable verbose logging to the Zotero error console |
|
|
|
|
## Usage
|
|
|
|
### Manual Export
|
|
|
|
- **Export all items**: **Tools → Export All Annotations to Org**
|
|
- **Export selected items**: Right-click one or more items → **Export Annotations to Org**
|
|
|
|
### Automatic Export
|
|
|
|
When enabled in preferences, exports happen automatically:
|
|
|
|
- After a Zotero sync completes (only items with new/changed annotations are exported)
|
|
- When you close a PDF or EPUB reader tab
|
|
|
|
### Output Format
|
|
|
|
Files are written to the configured Notes Directory, named by citation key:
|
|
|
|
```
|
|
~/org/notes/smith2020.org
|
|
~/org/notes/doe2019.org
|
|
```
|
|
|
|
Each file contains:
|
|
|
|
```org
|
|
#+title: The Full Title of the Referenced Work
|
|
|
|
* Annotation heading
|
|
Converted annotation text...
|
|
```
|
|
|
|
Only items that have a citation key (via Better BibTeX or the `citationKey` field) will be exported.
|
|
|
|
## For Maintainers
|
|
|
|
This section covers building, developing, and releasing the plugin.
|
|
|
|
### Architecture
|
|
|
|
```
|
|
src/
|
|
├── index.ts # Entry point: mounts addon to Zotero global
|
|
├── addon.ts # Core addon class (logging, init, module wiring)
|
|
├── hooks.ts # Lifecycle hooks (startup/shutdown, menu actions)
|
|
└── modules/
|
|
├── prefs.ts # Typed read/write for all preferences
|
|
├── exporter.ts # Attachment detection, sync checking, batch export
|
|
├── converter.ts # Markdown → Org via pandoc, file I/O
|
|
├── notifier.ts # Zotero event handlers (sync finish, tab close)
|
|
└── menu.ts # Menu registration (Zotero 7 + 8 compatible)
|
|
|
|
addon/ # Static plugin files copied verbatim into the XPI
|
|
├── manifest.json
|
|
├── bootstrap.js # Zotero plugin lifecycle entry point
|
|
├── prefs.js # Default preference values
|
|
└── content/
|
|
├── preferences.xhtml # Preferences pane UI (XUL)
|
|
├── scripts/preferences.js
|
|
├── icons/
|
|
└── locale/en-US/ # Fluent (.ftl) string bundles
|
|
```
|
|
|
|
The build system uses [zotero-plugin-scaffold](https://github.com/windingwind/zotero-plugin-scaffold) with esbuild, which bundles `src/` into a single `index.js` and packages everything as an XPI.
|
|
|
|
### Prerequisites
|
|
|
|
**With Nix (recommended):**
|
|
|
|
```bash
|
|
# Requires Nix with flakes enabled
|
|
nix develop
|
|
```
|
|
|
|
This provides Node.js 20, npm, TypeScript, ESLint, Prettier, and Pandoc.
|
|
|
|
**Without Nix:**
|
|
|
|
- Node.js 20+
|
|
- npm
|
|
- Pandoc (for manual testing)
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
### Environment Setup
|
|
|
|
Copy the environment template and fill in your local paths:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
Edit `.env`:
|
|
|
|
```bash
|
|
# Path to the Zotero binary (required for the dev server)
|
|
ZOTERO_PLUGIN_ZOTERO_BIN_PATH=/path/to/zotero
|
|
|
|
# Path to a Zotero development profile directory
|
|
ZOTERO_PLUGIN_PROFILE_PATH=/path/to/zotero-dev-profile
|
|
```
|
|
|
|
Create a dedicated Zotero profile for development to avoid affecting your main library.
|
|
|
|
### Development Workflow
|
|
|
|
```bash
|
|
# Start the dev server — builds and hot-reloads the plugin into a running Zotero instance
|
|
npm start
|
|
|
|
# One-off build — outputs XPI to .scaffold/build/
|
|
npm run build
|
|
|
|
# Lint TypeScript source
|
|
npm run lint
|
|
npm run lint:fix # auto-fix
|
|
|
|
# Format source files
|
|
npm run format
|
|
npm run format:check # check without writing
|
|
```
|
|
|
|
The dev server (`npm start`) watches for changes in `src/` and `addon/`, rebuilds, and reloads the plugin inside Zotero automatically. Zotero must already be running with the configured profile.
|
|
|
|
### Testing
|
|
|
|
There are no automated tests. To test manually:
|
|
|
|
1. `npm run build` to produce the XPI
|
|
2. Install the XPI in a Zotero 7 instance via **Tools → Add-ons → Install Add-on From File...**
|
|
3. Exercise the export functionality manually via the Tools menu and right-click context menu
|
|
|
|
### Releasing
|
|
|
|
Releases are created by pushing a version tag. The CI/CD pipeline (Gitea Actions) will build the XPI and publish a release automatically.
|
|
|
|
To cut a release locally:
|
|
|
|
```bash
|
|
npm run release
|
|
```
|
|
|
|
This runs [bumpp](https://github.com/antfu/bumpp) interactively to select the new version, then:
|
|
|
|
1. Updates `package.json` version
|
|
2. Commits and tags the version
|
|
3. Pushes the commit and tag to the remote
|
|
4. Builds the XPI
|
|
|
|
Once the tag is pushed, Gitea Actions takes over and creates the release with the XPI attached.
|
|
|
|
### Code Style
|
|
|
|
- **Formatter**: Prettier (config in `.prettierrc`) — double quotes, 2-space indent, semicolons
|
|
- **Linter**: ESLint with TypeScript-ESLint (config in `.eslintrc.js`) — strict mode
|
|
- **Naming**: PascalCase for classes/types, camelCase for functions/methods, UPPER_SNAKE_CASE for constants
|
|
- **Imports**: relative paths, `import type` for type-only imports, no namespace imports
|
|
- **Error handling**: always catch with a typed `error as Error`; use `_error` for non-critical ignores
|
|
|
|
See `AGENTS.md` for the full style guide used during AI-assisted development.
|
|
|
|
## License
|
|
|
|
GPL-3.0-or-later
|
|
|
|
## Credits
|
|
|
|
Based on the [zotero-plugin-template](https://github.com/windingwind/zotero-plugin-template) by windingwind.
|