Skip to content

Releases: jwingnut/zotero-batch-open

v0.3.5

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 10:14

Fix

Silent false success: the connector could report a job as
ok: true ("saved via translator") even though nothing was ever
created in Zotero -- proven against a live Zotero: two jobs logged as
successful, but a read-only query of zotero.sqlite for that time
window found neither item. Root cause was in the connector (a
cross-context browser message silently resolving to nothing without
throwing -- see the remote-trigger branch of zotero-connectors for
that fix).

This release adds the plugin-side half: GET /batchopen/confirm?jobId=...,
which the connector now polls before ever reporting success, asking
Zotero itself (via the same duplicate-matching the background
reconciliation already uses) whether a matching item has actually
appeared. A result must never again say OK when Zotero has nothing.

🤖 Generated with Claude Code

v0.3.4

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 09:35

Fixes

  • Reconciliation crash: the duplicate-matching fallback (QueueServer: findDuplicate) called Zotero.Items.getAll() with no arguments and expected a synchronous array back. The real API is async and requires a libraryID, so every fallback lookup threw TypeError: allItems.filter is not a function -- meaning reconciliation could never succeed for a job the connector reported no item keys for (e.g. a snapshot-fallback save). Fixed in both the automatic queue-reconcile path and the manual "Attach newly saved files" command, defensively: the item fetch is now awaited and validated as an array, with a descriptive error (naming the actual type) if it still isn't one, instead of a bare TypeError.

Cleanup needed for this run's leftovers

A run against a live Zotero library (before this fix) hit the bug above on an MDPI item (key BXWYFCP5): the connector saved a webpage snapshot instead of the real translator result (see the connector-side fix in the remote-trigger branch of zotero-connectors), and reconciliation failed to attach/reconcile it, leaving a stray duplicate item behind. To clean that up:

  1. Open item BXWYFCP5, delete the snapshot attachment it gained during that run.
  2. Select BXWYFCP5 (and any other affected items) and re-run the "Attach newly saved files to the selected items" (reconcile) command from the Batch Open menu -- it will find the stray duplicate item, move any usable attachment onto the original, and trash the emptied duplicate.

🤖 Generated with Claude Code

Batch Open 0.3.3

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 08:43

Fixes found by running the remote trigger end to end.

  • Redirects resolved before queuing. A DOI or linkinghub.elsevier.com URL is followed in Zotero first, so the browser opens the real article page instead of chasing the chain (which was the cause of "no translator detected").
  • Reconciliation waits for the file. The connector saves the item first and the PDF a moment later; we now wait up to 60 seconds for the attachment to appear before moving it onto your original item, and fall back to matching by DOI, identifier, or title and year when the browser reports no item keys.
  • filesMoved=0 is no longer reported as success. A result says whether the file moved, or that the save happened but no attachment appeared, or that no matching item was found.
  • New preference: reconcile saved items (default on). Off leaves the newly saved item alone for a duplicate-merging plugin. On keeps your original item's collections, tags, notes and Better BibTeX citation key, which a later merge can otherwise change.
  • New GET /batchopen/status so the browser extension can show queue depth.

Use with the companion Connector fork rebuilt as 5.0.214+batchopen.1.

v0.3.2

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 07:26

What's fixed

The remote-trigger poller couldn't reach Zotero at all. In Chrome (Manifest V3), the browser puts every extension's background work into a "service worker" that periodically goes idle and wakes back up. When that service worker made its own raw network requests to talk to Zotero, Chrome silently attached an extra identifying header that Zotero's local server doesn't accept from anyone but its own official connector -- so every request from the poller was dropped with no response, and nothing ever got saved. This release fixes that by having the poller use the same internal request path the official Zotero Connector already uses, instead of making the request itself. (This fix ships in the separate zotero-connectors browser extension, not in this plugin's .xpi -- see that repo's remote-trigger branch.)

Hardened the job-queue endpoint. The endpoint that hands jobs to the poller now accepts a few different shapes of the "how many jobs at once" request parameter instead of assuming one exact shape, and if it ever can't understand what was asked for, it defaults to "no limit" rather than quietly handing back zero jobs. It also now logs every time the poller checks in, including when there was nothing to hand out -- so a genuinely stuck queue is easy to tell apart from a poller that never checked in at all.

If something looks stuck

Use "Clear the connector queue" from the Batch Open menu. It empties both pending and in-progress jobs so you can start over without restarting Zotero. (A job that's shown as "in progress" also recovers on its own after 5 minutes if nothing reports back.)

v0.3.1

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 05:59

Fixes from a real run

A live run with the zotero-connectors remote-trigger fork surfaced three
bugs in the same session, all fixed in this release:

  • Duplicate jobs when re-running "Save selected via connector". Running
    the command twice before the connector's poller had started queued the
    same 7 items twice. Enqueueing now skips (and reports as "already
    queued") any item that already has a pending or in-flight job.
  • No way to clear a stuck queue without restarting Zotero. Added a new
    Batch Open → Clear the connector queue menu command that empties
    pending and in-flight jobs and reports how many were removed.
  • A false "UNAVAILABLE" verdict from the plugin's own self-test. The
    self-test used a loopback fetch() that Zotero blocks internally, so it
    always failed and logged "the remote trigger is UNAVAILABLE" — even in
    the same run where the browser connector successfully fetched 7 real
    jobs from the endpoint one second later. The self-test has been removed;
    registration now logs a plain factual line ("registered; awaiting the
    first poll from the browser") instead of a verdict it had no way to make
    honestly.

Also: GET /batchopen/queue now accepts an optional ?max= parameter so a
poller can ask for fewer than the default 25-job batch at a time — used by
the matching fix on the zotero-connectors side (branch remote-trigger),
where the browser-extension poller now wakes via a chrome.alarms schedule
and processes one job per wake instead of a long-lived loop, so it survives
Chrome's periodic eviction of the extension's background service worker.

npm test (156/156), npm run lint:check, and npm run build all pass.

🤖 Generated with Claude Code

Batch Open 0.3.0

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 05:28

If you installed 0.2.0 and Zotero showed 0.1.4, this is the fix. The 0.2.0 package carried the wrong version inside it because the manifest was never bumped; the version is now generated from one place, so the number you see is the build you have.

New since 0.1.4

  • Open all in browser (only those missing a PDF) — skips items that already have a stored file, so you open the tabs that actually need saving.
  • Attach newly saved files to the selected items — after you save tabs with the Connector, this moves those PDFs onto your original items and sends the leftover duplicates to the trash (trash, never deleted). Matching is DOI first, then PMID or arXiv, then title with an exact year and a 95% similarity floor.
  • Save selected via connector — publishes a queue on Zotero's local server for the companion Connector fork, which opens each page, saves it, and closes the tab. See REMOTE_TRIGGER.md.
  • A new preference for how far back to look for duplicates (default 120 minutes).

Install: download batch-open.xpi, then Zotero → Tools → Add-ons → gear → Install Add-on From File, and restart Zotero.

v0.2.0

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 04:50

What's new

Two new commands support the "browser save → reconcile" workflow for
libraries with browser-only (VPN) database access:

  • Open all in browser (only those missing a PDF) — filters the
    selection to regular items with no stored/imported PDF attachment
    before opening tabs (a linked-URL attachment does not count), and
    reports how many were skipped.
  • Attach newly saved files to the selected items — for each
    selected original item, finds a Zotero Connector-created duplicate
    top-level item added to the same library within a configurable
    window (default 120 minutes; extensions.zotero.batchopen.reconcileWindowMinutes)
    and matches it by normalized DOI, then PMID/arXiv id (from Extra),
    then a strict title+year match. On a match it moves the duplicate's
    stored/imported file attachments (PDFs and snapshots) onto the
    original and moves the emptied duplicate to the trash (never a
    permanent delete — fully reversible). An original's existing
    attachments are never touched; if both already had a PDF, both are
    kept. Always confirms first, naming exactly how many files will be
    attached and how many duplicates will be trashed. Every match
    decision is logged to batch-open.log.

How the workflow fits together

  1. Select items missing a PDF and run "Open all in browser (only
    those missing a PDF)".
  2. Press the Zotero Connector's save button on each opened tab.
  3. Re-select the original items and run "Attach newly saved files to
    the selected items" to merge the connector's duplicates back onto
    the originals.

Install: Zotero → Tools → Add-ons → gear icon → Install Add-on From
File..., and choose batch-open.xpi from this release.

🤖 Generated with Claude Code

Batch Open 0.1.4

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 04:28

Menu labels no longer depend on locale resolution: the item context menu now
registers without a Fluent l10nID by default (labels are set directly when
the menu shows), falling back to the l10nID-based registration only if that
fails. English-variant locales (en-GB, en-AU, en-CA, en-NZ) are now shipped
alongside en-US, so a non-US English locale chain can still resolve our
strings. The plugin now writes a small batch-open.log file in the Zotero
data directory (or the profile directory as a fallback), so a failure can be
diagnosed without opening the Debug Output Logging console.

🤖 Generated with Claude Code

Batch Open 0.1.3

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 03:10

This release adds diagnostics and hardening in response to a report of "Uncaught (in promise) undefined" on repeated use of Batch Open, with nothing about the failure showing in the Zotero error console.

What changed:

  • Every menu callback and the batch-open command itself now go through a guard that catches both a synchronous throw and a rejected promise -- including one that rejects with no value at all -- and logs it with its type and a stack trace when available, instead of letting it disappear as a bare, untraceable rejection.
  • All interactions with the progress window (the little "Opening N of M..." popup) are now guarded individually. If that window has already closed -- for example because it was clicked (it closes on click) or its own auto-close timer already fired -- Batch Open now logs that and falls back to a toast message instead of throwing.
  • Batch Open now logs its version on startup, one line per command you run (which command, how many items selected), and one line when it finishes or fails -- all searchable in Zotero's Help -> Debug Output Logging -> View Output by searching for "Batch Open".
  • The progress window headline now shows the running version, e.g. "Batch Open 0.1.3 - opened 12 of 12", so you can tell at a glance which build is installed.

Honesty about root cause: the exact original trigger could not be reproduced or confirmed directly (Zotero couldn't be run interactively in this environment), so this release should be read as making the failure mode impossible to hide and closing the most likely source (an unguarded call into an already-closed progress window), not as a confirmed fix for one specific bug. If it recurs, Help -> Debug Output Logging -> View Output will now contain a "Batch Open" line naming exactly what failed -- please share that line if you see this again.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01PVRWMyomrJT6SUpdPPhqA6

Batch Open 0.1.2

Choose a tag to compare

@jwingnut jwingnut released this 03 Sep 02:55

Adds automatic updates and the plugin icon.

Install: download batch-open.xpi below, then Zotero → Tools → Add-ons → gear → Install Add-on From File. From this version on, Zotero checks for updates itself and will offer later versions without another manual download.

Changes since 0.1.1

  • Auto-update: the plugin publishes update.json alongside each release and the manifest points at it.
  • An icon, shown in Zotero's add-ons list.

What the plugin does. Select any number of items, right-click, and use the Batch Open submenu:

  • Open all in browser — each item's URL, else its DOI, else a child attachment's URL, else your configured fallback.
  • Search all in Google Scholar — title, first author and year.
  • Search all in web search — the same, through a search engine you configure.

Settings cover the fallback, the search template, a confirmation threshold (default 25 items) and the delay between tabs (default 300 ms, which keeps Google Scholar from serving a CAPTCHA). A progress window reports as it goes, and the summary says how many opened from a URL, how many from a DOI, how many fell back to a search, and what was skipped.

Requires Zotero 8 or later; tested against Zotero 10.