cd /news/developer-tools/generating-a-link-to-an-annotation-i… Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-13200] src=gist.github.com β†— pub= topic=developer-tools verified=true sentiment=Β· neutral

Generating a link to an annotation in Zotero

Based on the provided code, this is a Bash script that generates formatted links or citations from Zotero annotations. It extracts a Zotero item ID from clipboard text, queries a BetterBibTeX JSON export of the user's Zotero library, and outputs a link, citekey, or formatted quote depending on the mode selected. The script requires `jq` and either `pbpaste` or `xsel` to function.

read2 min views28 publishedNov 15, 2024

zotero-link.sh

  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

Show hidden characters

#!/usr/bin/env bash

export LC_ALL=en_US.UTF-8

#

mode="${1:-link}" library="$HOME/Base/Obsidian/.library.json"

fail() {

  printf 'zotero-link: %s\n' "$*" >&2

exit 1

} #─────────────────────────────────────────────────────────────────────────────

if command -v pbpaste >/dev/null 2>&1; then

  text=$(pbpaste)

elif command -v xsel >/dev/null 2>&1; then

  text=$(xsel --clipboard --output)

else

fail "could not find pbpaste or xsel"

fi

command -v jq >/dev/null 2>&1 || fail "jq is not installed"

[[ -r "$library" ]] || fail "library file is not readable: $library"

#─────────────────────────────────────────────────────────────────────────────

id=$(printf '%s\n' "$text" |

  grep -Eo 'zotero://select/library/items/[a-zA-Z0-9]+' |

sed 's|zotero://select/library/items/||' |

  head -n 1)

if [[ -z "$id" ]]; then

  id=$(printf '%s\n' "$text" |

    grep -Eo 'zotero://open-pdf/library/items/[a-zA-Z0-9]+' |

    sed 's|zotero://open-pdf/library/items/||' |

    head -n 1)

fi

if [[ -z "$id" ]]; then fail "could not find Zotero item ID in the clipboard text"

fi

#─────────────────────────────────────────────────────────────────────────────

item=$(jq --arg key "$id" '

  .items[]

| select(

      .key == $key

      or any(.attachments[]?; (.select == ("zotero://select/library/items/" + $key)) or (.uri | endswith("/items/" + $key)))

    )

' "$library")

title=$(jq -r 'if .shortTitle then .shortTitle else .title end' <<<"$item")

if [[ -z "$title" ]]; then

fail "could not find exported Zotero item or parent attachment for ID: $id"

fi

#─────────────────────────────────────────────────────────────────────────────

if [[ "$mode" == "citekey" ]]; then

  citekey=$(jq -r '.citationKey' <<<"$item")

  echo "[@${citekey#@}]"

exit 0

fi

#─────────────────────────────────────────────────────────────────────────────

link_patterns=(

  "pdf:zotero:\/\/open-pdf\/library\/items\/([a-zA-Z0-9]+)\?page=([0-9]+)&annotation=([a-zA-Z0-9])+"

  "snap:zotero:\/\/open-pdf\/library\/items\/([a-zA-Z0-9]+)\?sel=([^&]+)&annotation=([a-zA-Z0-9]+)"

  "epub:zotero:\/\/open-pdf\/library\/items\/([a-zA-Z0-9]+)\?cfi=([^&]+)&annotation=([a-zA-Z0-9]+)"

)

#─────────────────────────────────────────────────────────────────────────────

for pattern in "${link_patterns[@]}"; do

  IFS=':' read -r link_type regex <<<"$pattern"

  if [[ "$text" =~ $regex ]]; then

    link="${BASH_REMATCH[0]}"

    page_number="${BASH_REMATCH[2]}"

    case "$mode" in

    quote)

      quote_text=$(printf '%s' "$text" | sed 's/ *(\[.*//')

      author_full=$(jq -r 'if .creators[0] then "\(.creators[0].firstName) \(.creators[0].lastName)" else empty end' <<<"$item")

      echo "> [!quote]"

      echo "> ${quote_text//$'\n'/$'\n> '}"

      echo ">"

      case "$link_type" in

      pdf) echo "> - ${title}, [p. ${page_number}](${link})" ;;

      *) echo "> - [${title}](${link})" ;;

      esac

      [[ -n "$author_full" ]] && echo "> - ${author_full}"

      ;;

    *)

      author=$(jq -r '.creators[0].lastName // empty' <<<"$item")

      year=$(jq -r '.date // empty' <<<"$item" | grep -Eo '[0-9]{4}')

      result=""

      [[ -n "$author" ]] && result="${author}, "

      case "$link_type" in

      pdf)

        result="${result}${title}"

        [[ -n "$year" ]] && result="${result} (${year})"

        result="${result}, [p. ${page_number}](${link})"

        ;;

      *)

        result="${result}[${title}](${link})"

        [[ -n "$year" ]] && result="${result} (${year})"

        ;;

      esac

      echo "$result"

      ;;

    esac

    exit 0

fi

done

fail "no suitable Zotero PDF/snapshot/EPUB link found in the clipboard text"

── more in #developer-tools 4 stories Β· sorted by recency
── more on @zotero 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/generating-a-link-to…] indexed:0 read:2min 2024-11-15 Β· β€”