Automating Zotero with AppleScript (and JavaScript)

Automating Zotero with AppleScript (and JavaScript)

Learn how to improve efficiency working with citations within the Zotero application using macOS.

5 min read

Zotero background

I recently published an article detailing some AppleScripts that I use for ReadCube Papers, and I thought it would be useful to show additional scripts that I used for Zotero. Zotero is an open-source bibliography software package that manages PDF documents and provides the ability to export citations to literature cited formats for hundreds of journals.

💡
As with the article on ReadCube Papers, these scripts will need to be executed with a third-party utility such as FastScripts or Keyboard Maestro, as I described in my previous post. Using Keyboard Maestro, built-in tools such as keystroke and menu selection will be an easier way to accomplish what is done in the scripts below. If you prefer to script your automation directly, this post is for you.

Swap first name and last name in the authors’ field

When I imported my ReadCube Papers library into Zotero, the author’s first name and last name did not map correctly for several citations. In my case, the authors’ names were in firstname lastname format in the lastname field. Using GUI scripting, I used AppleScript to move the first name to the correct field and leave the last name where it was, rather than manually doing a copy and paste for each author. GUI scripting involves manually simulating keystrokes that mimic selecting words, copying text, tabbing to a new field, and pasting the text.

For the script below to work, both the author's first name and last name must be in the lastname field and in the first name last name order. Assuming this is true, and the cursor is placed at the beginning of the lastname field, the script will move the first name to the correct field and leave the last name as is. Key code 123 is the right arrow key.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application "System Events"
	tell process "Zotero"
		key code 123 using {shift down, option down}
		delay 0.1
		keystroke "x" using command down
		delay 0.1
		keystroke tab
		delay 0.1
		keystroke "v" using command down
		delay 0.1
		keystroke tab
	end tell
end tell

This script simulates keystrokes to highlight the first name, cut the first name, tab from the lastname field to the firstname field, and paste the first name into the firstname field.

Saving this script in the ~/Library/Scripts/Applications/Zoterofolder will make the script available in FastScripts when Zotero is the front application. To trigger this script, I used an unused function key, F16, which was convenient to type multiple times if there were numerous author names to swap. The keystroke tab line in the above script automatically moves the cursor to the next author, so this does not need to be done manually. The F16 key can either be pressed again to perform the same operation on the next author or ignored if all author first and last names have been populated correctly.

Selecting menu items via keyboard shortcuts

Note that these scripts that select menu items could also be done with the macOS built-in keyboard shortcut feature in the keyboard system preferences. I use the scripting approach to manage all the keyboard shortcuts in one place (rather than having shortcuts in system preferences and shortcuts in FastScripts). However, using the keyboard system preferences does not require a third-party utility.

Changing the display font size

Several menu items in Zotero don't have a keyboard shortcut where one would be helpful. These menu items include the following:

  • Making the text larger and smaller
  • Displaying the run JavaScript window

Using a handler from MacScripter, I used the following arguments with the do_submenu handler to increase the Zotero font size:

do_submenu("Zotero", "View", "Font Size", "Bigger"). Handlers allow you to reuse code snippets easily.

The full AppleScript with the handler and the execution of the handler is here:


do_submenu("Zotero", "View", "Font Size", "Bigger")

on do_submenu(app_name, menu_name, menu_item, submenu_item)
	try
		-- bring the target application to the front
		tell application app_name
			activate
		end tell
		tell application "System Events"
			tell process app_name
				tell menu bar 1
					tell menu bar item menu_name
						tell menu menu_name
							tell menu item menu_item
								tell menu menu_item
									click menu item submenu_item
								end tell
							end tell
						end tell
					end tell
				end tell
			end tell
		end tell
		return true
	on error error_message
		return false
	end try
end do_submenu

Show JavaScript window

Because I often bulk edit metadata in Zotero to ensure consistency, I like to have quick access to the JavaScript window that makes this possible. This script is similar to the one used to change the font size, but the first line points to a different menu item. Pasting the code below in an empty Script Editor window and saving the script here ~/Library/Scripts/Applications/Zotero makes the script accessible to FastScripts when Zotero is the frontmost application. I assigned a keyboard shortcut of ⌘J, as this is currently not used by Zotero.

do_submenu("Zotero", "Tools", "Developer", "Run JavaScript")
on do_submenu(app_name, menu_name, menu_item, submenu_item)
	try
		-- bring the target application to the front
		tell application app_name
			activate
		end tell
		tell application "System Events"
			tell process app_name
				tell menu bar 1
					tell menu bar item menu_name
						tell menu menu_name
							tell menu item menu_item
								tell menu menu_item
									click menu item submenu_item
								end tell
							end tell
						end tell
					end tell
				end tell
			end tell
		end tell
		return true
	on error error_message
		return false
	end try
end do_submenu

Bulk changing metadata with JavaScript

As of version 6.04, Zotero does not have built-in support for bulk changing metadata. For example, if I wanted to rename J Appl Ecol to Journal of Applied Ecology in multiple articles, I would have to edit the journal field manually for each entry that I wanted to change. Fortunately, Zotero has support for JavaScript within the application, and using a script from the Zotero wiki, I was able to modify it to perform the journal renaming just described.

To use the script below,

  1. Back up your current Zotero library. While I’ve used this script many times myself without any issues, if you’ve never used it, you should have a backup of your library in case it doesn’t work as expected. You have been warned.
  2. Select the items from the Zotero library that you want to change the journal name for.
  3. Paste the following code into the JavaScript window. Using the previous script, you can assign a keyboard shortcut to this menu item.
  4. Change the values of the 2nd and 3rd lines to the name of the journal you would like to replace and the new name, respectively.
  5. Run the script
var fieldName = "publicationTitle";
var oldValue = "J Appl Ecol";
var newValue = "Journal of Applied Ecology";
 
var fieldID = Zotero.ItemFields.getID(fieldName);
var s = new Zotero.Search();
s.libraryID = ZoteroPane.getSelectedLibraryID();
s.addCondition(fieldName, 'is', oldValue);
var ids = await s.search();
if (!ids.length) {
    return "No items found";
}
await Zotero.DB.executeTransaction(async function () {
    for (let id of ids) {
        let item = await Zotero.Items.getAsync(id);
        let mappedFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(item.itemTypeID, fieldName);
        item.setField(mappedFieldID ? mappedFieldID : fieldID, newValue);
        await item.save();
    }
});
return ids.length + " item(s) updated";

Note that the first line of this script can be modified to bulk change other metadata fields. The complete list of fields is available on the Zotero website. From that list, the field name is what you enter on the first line of the script, and the localized name is the plain English description of the field.

Finishing up

The above scripts can be adapted to your Zotero workflow to automate the interface to make for more efficient interactions with the application. Using the JavaScript window is particularly helpful for bulk metadata changes when cleaning up your Zotero library.

Comments