# Create bibliographies from Zotero collections
library(jsonlite)
library(fs)
library(janitor)
library(tidyverse)
library(bib2df)
library(knitr)
library(httr2)
# Input and output paths for attached PDFs
PATH_ZOTERO <- Sys.getenv("PATH_ZOTERO")
stopifnot(PATH_ZOTERO != "") # Hack to require a proper path
PATH_OUT <- "bibliography/files"
# Get publications as jzon (BetterBibTeX JSON debug format) from local Zotero API
# https://retorque.re/zotero-better-bibtex/exporting/pull/index.html
dat <- request(
"http://127.0.0.1:23119/better-bibtex/export?/library;name:My%20Library/collection/cv/cv.jzon"
) |>
req_perform() |>
resp_body_string() |>
fromJSON() |>
pluck("items") |>
tibble()
# Copy files from Zotero storage to repaired paths here
dat <- dat |>
mutate(
file = map_chr(attachments, ~ pluck(.x, "path", .default = NA_character_)),
path = str_replace(file, PATH_ZOTERO, PATH_OUT)
)
walk2(
dat$file,
dat$path,
~ if (!is.na(.y)) {
dir_create(dirname(.y))
file_copy(.x, .y, overwrite = TRUE)
}
)
# Wrangle data
# Choose only specific item types
dat <- dat |>
clean_names() |>
filter(
item_type %in%
c("journalArticle", "preprint", "presentation", "computerProgram", "book")
)
# Different types have different source names
dat <- dat |>
mutate(
source = coalesce(publication_title, repository, publisher, place)
)
# Create a string of authors' last names
dat <- dat |>
mutate(
authors = map_chr(
creators,
~ combine_words(.x$lastName, and = " & ", oxford_comma = FALSE)
)
)
# Create a string of comma-separated tags
dat <- dat |>
mutate(
tags = map_chr(
tags,
~ pluck(.x, "tag", .default = "") |>
combine_words(and = "") |>
str_to_lower()
)
)
# Write a YAML file for Quarto listing
# Note the Zotero 'Extra' field can contain items like
# license: CC-BY
# data: <URL>
dat |>
mutate(extra = ifelse(is.na(extra), "extra: ~", extra)) |>
str_glue_data(
"
- title: >-
{title}
url: {url}
date: {date}
type: {item_type}
authors: '{authors}'
doi: {doi}
source: >-
{source}
file: {path}
meeting: >-
{meeting_name}
categories: [{tags}]
abstract: |
{str_remove_all(abstract_note, '\\n')}
{str_replace_all(extra, '\\n', '\\n ')}
"
) |>
cat(file = "bibliography/items.yml", sep = "\n")