Zotero export notes

Zotero notes-with-tags and embedded images

What I’m trying to do

I posted on discourse but have realised it’s probably not the best structure for the question.

I have a group Zotero library in which we create notes from annotations + tag the notes. I’d like to export the notes with tags + parent metadata + any images in the notes.

I want to do that because then we can keep the link between note<->source really tight in Zotero, and between metadata<->knowledge-structuring really tight within Obsidian and use dataviews to e.g. create a table of notes tagged ‘researchquestion’ by item.

Things I have tried

Approaches I’ve tried

  1. On Zotero side, the general export doesn’t include tags, Better Notes plugin is cool, but it seems not to scale well so for a collection it falls over. You could use e.g. the cites plugin discussed here too, but it’s a wholesale move of notes to obsidian
  2. On the Obsidian side:
    1. The md notes zotero plugin which acts as a bridge, through it you should be able to one-off export to .md and then import into Obsidian (no continuous updating) per this discussion on the zotero forums or here on the obsidian forums and here - I’m ok with this approach but I’m not clear what functionality is working in md notes, and for me at least the menus don’t appear in Zotero ( per bug report )
    2. mgmyers zotero obsidian integration plugin - using that with the classic zotero selector you can select multiple items, following template description. This approach has cool potential, and there’s a great guide using this approach on setting up for academic writing using pandoc
    3. zotero plugin per forum and on github here - no documentation at all at the moment (although it seems people are using it, so I may just be particularly dumb :-)).
    4. and bibnotes formatter discussed here and on github here - I didn’t explore this one much, seems to be very similar to 1-3.

The 3rd option seems cool because it’s actually connecting directly to the zotero sqlite, but there isn’t enough of a manual for me to navigate setting it up.

The 2nd seems to do a lot and is quite widely used. I’m struggling a bit with the templates (can I run a template to bulk import and split by note ID each with its own yaml?, etc.), but did get this great notetaking for historians template working.

Issues

More importantly, in using the Zotero Integration, on looking at the Zotero Data Explorer I can see that:

  1. Notes are separate to annotations, and they do not share tags (this makes sense as they can be tagged separately in Zotero too) (separate but possibly related, there’s a pull request for annotation tag processing it seems https://dorian-groll/obsidian-zotero-integration/tree/add_tags_to_annotations )
  2. As far as I can see using {%- for note in notes %} {% for t in note.tags %}{{t.tag}}{% if not loop.last %}, {% endif %}{% endfor %} doesn’t work - no tags are output for the notes (and, no note text)
  3. the embedded images are links to the annotations, so including them would need some script to map the identifier as e.g. " [Go to annotation](zotero://open-pdf/library/items/2WUYWGW8?page=7368&annotation=I68R57L5) here I68R57L5 to the image path where the annotation.type is image (rather than highlight)

I think this kind of workflow would be quite common, and I can see the enormous potential of integration for e.g. running evidence synthesis exercises. Have I missed something / overcomplicated, or, any advice much appreciated!

For clarity: I want to select multiple zotero items, where each item has child notes that contain (1)annotation images and (2) tags. I want those notes as separate md in obsidian, with the images embedded, and the tags in the yaml.

I’ve got part way (building off the template guide and initial template here. This broadly works (which is cool, I’ve never used nunjucks before), but the replacement isn’t functioning.

From trying to output it (on an item I know has annotation.type image), I can see this filter isn’t working at the very least…but I’m not sure why?

{% set annotationImage = annotations | filterby("type", "contains", "image") %}

Rest of template


---
#cssclass: research-note
type: "{{itemType}}"{% for type, creators in creators | groupby("creatorType") -%}{% if loop.first %}
{% endif %}{{type | replace("interviewee", "author") | replace("director", "author") | replace("presenter", "author") | replace("podcaster", "author") | replace("programmer", "author") | replace("cartographer", "author") | replace("inventor", "author") | replace("sponsor", "author")  | replace("performer", "author") | replace("artist", "author")}}: "{%- for creator in creators -%}{%- if creator.name %}{{creator.name}}{%- else %}{{creator.lastName}}, {{creator.firstName}}{%- endif %}{% if not loop.last %}; {% endif %}{% endfor %}"{% if not loop.last %}
{% endif %}{%- endfor %}{% if title %}
title: "{{title}}"{% endif %}{% if publicationTitle %}
publication: "{{publicationTitle}}"{% endif %}{% if date %}
date: {{date | format("YYYY-MM-DD")}}{% endif %}{% if archive %}
archive: "{{archive}}"{% endif %}{% if archiveLocation %}
archive-location: "{{archiveLocation}}"{% endif %}
citekey: {{citekey}}
tags: {% for t in tags %}{{t.tag}}{% if not loop.last %}, {% endif %}{% endfor %}
---

{{bibliography}}
[online]({{uri}}) [local]({{desktopURI}}) {%- for attachment in attachments | filterby("path", "endswith", ".pdf") %} [pdf](file://{{attachment.path | replace(" ", "%20")}})
{% if loop.last %} 
{% endif %}{%- endfor %}
 
{% if tags.length > 0 -%}{% for t in tags -%}#{% if t.tag == "secondary" %}source/secondary{% if not loop.last %}{% endif %}{% elif t.tag == "primary" %}source/primary{% if not loop.last %}{% endif %}{% elif "-project" in t.tag %}project/{{t.tag | lower | replace(" ", "-") | replace("-project", "")}}{% else %}subject/{{t.tag | lower | replace(" ", "-")}}{% endif %}{% if not loop.last %}
{% endif %}{%- endfor %}{%- endif %}

### Connections

comment:: 


### notey mcnote face
{% set notes = notes -%}
{% if notes.length > 0 %}

### Imported on {{importDate | format("YYYY-MM-DD h:mm a")}}

{%- for note in notes %}

#### parentitem
{{note.parentItem}}

#### tags
{% for t in note.tags %}{{t.tag}}
	{% if not loop.last %}, 
	{% endif %}
{% endfor %}

#### note relations
{% if note.relations > 0 %}
	{{note.relations}}
{% endif %}

#### note content
<!-- Make a list of annotations that are images. We'll be using annotation.imagePath, and annotation.id -->

{% set annotationImage = annotations | filterby("type", "startswith", "image") %}

<!-- if annotation.id is in this note, use a replace to keep the link to the annotation, and add on the imageRelativePath-->
{% if annotationImage > 0 %}
	{% for annotation in annotationImage %}
		{% if annotation.id in note.note %}
			{% set idx = [annotation.id, ")"] | join %}
			 {% set idxreplace = [")", annotation.imageRelativePath] | join %}
			{{ note.note | replace(idx, idxreplace) }}
			
		{% endif %}
	{% endfor %}
{% endif %}

<!-- return the modified note-->
{{note.note}}

{%- endfor %}
{% endif %}

I’ve now got this mostly working, except the way I’m modifying/replacing in the notes means that for a note with 3 images, I get 3 copies of the note from the for… (so each copy has 1 image edited). I assume that’s a simple fix but I don’t know the syntax well enough.

---
type: "{{itemType}}"{% for type, creators in creators | groupby("creatorType") -%}{% if loop.first %}
{% endif %}{{type | replace("interviewee", "author") | replace("director", "author") | replace("presenter", "author") | replace("podcaster", "author") | replace("programmer", "author") | replace("cartographer", "author") | replace("inventor", "author") | replace("sponsor", "author")  | replace("performer", "author") | replace("artist", "author")}}: "{%- for creator in creators -%}{%- if creator.name %}{{creator.name}}{%- else %}{{creator.lastName}}, {{creator.firstName}}{%- endif %}{% if not loop.last %}; {% endif %}{% endfor %}"{% if not loop.last %}
{% endif %}{%- endfor %}{% if title %}
title: "{{title}}"{% endif %}{% if publicationTitle %}
publication: "{{publicationTitle}}"{% endif %}{% if date %}
date: {{date | format("YYYY-MM-DD")}}{% endif %}{% if archive %}
archive: "{{archive}}"{% endif %}{% if archiveLocation %}
archive-location: "{{archiveLocation}}"{% endif %}
citekey: {{citekey}}
tags: {% for t in tags %}{{t.tag}}{% if not loop.last %}, {% endif %}{% endfor %}
---

{{bibliography}}
[online]({{uri}}) [local]({{desktopURI}}) {%- for attachment in attachments | filterby("path", "endswith", ".pdf") %} [pdf](file://{{attachment.path | replace(" ", "%20")}})
{% if loop.last %} 
{% endif %}{%- endfor %}
 
{% if tags.length > 0 -%}{% for t in tags -%}#{% if t.tag == "secondary" %}source/secondary{% if not loop.last %}{% endif %}{% elif t.tag == "primary" %}source/primary{% if not loop.last %}{% endif %}{% elif "-project" in t.tag %}project/{{t.tag | lower | replace(" ", "-") | replace("-project", "")}}{% else %}subject/{{t.tag | lower | replace(" ", "-")}}{% endif %}{% if not loop.last %}
{% endif %}{%- endfor %}{%- endif %}

### Connections

comment:: 


### notey mcnote face
<!-- Make a list of annotations that are images by filtering on annotation.type. We'll be using annotation.imagePath, and annotation.id -->
{%- set annotationImage = annotations | filterby("type", "contains", "image") -%}

{% set notes = notes -%}
{% if notes.length > 0 %}

### Imported on {{importDate | format("YYYY-MM-DD h:mm a")}}

{%- for note in notes %}

#### parentitem
{{note.parentItem}}

#### tags
{% for t in note.tags %}{{t.tag}}
	{% if not loop.last %}, 
	{% endif %}
{% endfor %}

#### note relations
{% if note.relations > 0 %}
	{{note.relations}}
{% endif %}

#### note content

<!-- if annotation.id is in this note, use a replace to keep the link to the annotation, and add on the imageRelativePath-->
{% if annotationImage %}
	{% for annotation in annotationImage %}
	{% set idx = [annotation['id'], ")"] | join %}
	{% set idxreplace = [idx, " ![[{{", annotation['imageRelativePath'], "}}]]"] | join %}
		{% if annotation['id'] in note.note %}
			{{ note.note | replace(idx, idxreplace) }}
		{% endif %}
	{% endfor %}
{% endif %}
<!-- return the modified notes-->
{{note.note}}

{%- endfor %}
{% endif %}

1 Like