Zotero Integration – Import Templates?

Hya espalia,

I have adopted your template (although without grouping as that results in even worse issues for some reason) because its pretty close to what I intend, but I am encountering issues where callouts do not contain the entire comment if a comment has a list structure:

Source in Zotero:


You see here two sets of notes. The upper one is formatted as a standard list which would be renderable in markdown - item X), the lower one just uses paragraphs and doesn’t use a list syntax (- is missing)

When importing, I get this result:


Suggesting that lists are broken.

I don’t know why that is the case, nor do I know how to fix it. I’m having enough trouble understanding the nunjucks syntax as is, hence I’m posting here hoping someone has an answer.

Try putting an empty line (\n for ‘new line’ could be what you need) before your comments.

Do you mean in Zotero while annotating, or in the template within obsidian?

In the Template, of course.

I try to use this exact same template and it can’t generate the information like in the template.
The picture shows what the plugin generate.
Can someone please help me?

2 Likes

Here’s my template, inspired by @mgmeyers and @erazlogo. However, I only use callouts for the info and the abstract. The annotations and comments are formatted as a bullet list, where comments are listed in bold before the highlight they belong to, which is indented below and highlighted using ==highlight==. If a highlight has tags, those are listed next to the highlight.

EDIT: A new and improved version of this template is available here: Zotero Integration – Import Templates? - #105 by Feralflora

The annotations are grouped by color under different headings.

---
citekey: {{citekey}}
aliases: [{% if shortTitle %}"{{shortTitle | safe}}"{% else %}"{{title | safe}}"{% endif %}]
title: "{{title}}"
authors: {{authors}}
tags: [literature-note, {% for t in tags %}{{t.tag}}{% if not loop.last %}, {% endif %}{% endfor %}]
year: {{date | format("YYYY")}}
publisher: "{{publicationTitle}}"
doi: {{DOI}}
---

# [{{title}}]({{desktopURI}})

> [!info]+
>{% if bibliography %}**Bibliography:** {{bibliography}}{% endif %}
>
>**Page-no:** {% for annotation in annotations %}{% if loop.first %}{{annotation.pageLabel}}{% endif %}{% endfor %}
>
>{% if hashTags %}**Tags:** {{hashTags}}{% endif %}
>
>{%- for attachment in attachments | filterby("path", "endswith", ".pdf") %}**PDF:** [{{attachment.title}}](file:///{{attachment.path | replace(" ", "%20")}}){%- endfor %}
>
>[**Open in Zotero**]({{desktopURI}})
>[**Open DOI**](https://doi.org/{{DOI}})

> [!abstract]-
> {% if abstractNote %}
> {{abstractNote|replace("\n"," ")}}
> {% endif %}
 
---

## Notes
{% macro heading(color) -%}
{%- if color == "#5fb236" -%}
💡 Main ideas, contributions and conclusions
{%- endif -%}
{%- if color == "#2ea8e5" -%}
❔ Questions
{%- endif -%}
{%- if color == "#ffd400" -%}
⭐ Important
{%- endif -%}
{%- if color == "#a28ae5" -%}
🧩 Definitions and concepts
{%- endif -%}
{%- if color == "#ff6666" -%}
⛔ Weaknesses and caveats
{%- endif -%}
{%- endmacro -%}


{% persist "annotations" %}
{% set annotations = annotations | filterby("date", "dateafter", lastImportDate) -%}
{% if annotations.length > 0 %}

*Imported on {{importDate | format("YYYY-MM-DD HH:mm")}}*

{% for color, annotations in annotations | groupby("color") -%}

### {{heading(color)}}

{%- for annotation in annotations -%}
{%- if annotation.imageRelativePath %}
![[{{annotation.imageRelativePath}}]]
{%- endif %}
{%- if annotation.comment %}
- **{{annotation.comment}}:**
	- =={{annotation.annotatedText | nl2br}}== [(p. {{annotation.pageLabel}})](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.pageLabel}}&annotation={{annotation.id}}) {% if annotation.hashTags %}{{annotation.hashTags}}{% endif %}
{%- elif annotation.annotatedText %}
- =={{annotation.annotatedText | nl2br}}== [(p. {{annotation.pageLabel}})](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.pageLabel}}&annotation={{annotation.id}}) {% if annotation.hashTags %}{{annotation.hashTags}}{% endif %}
{%- endif -%}{%- endfor %}

{% endfor -%}
{% endif %}
{% endpersist %}

{{abstractNote|replace("\n"," ")}} The replace filter ensures that the abstract stays within the callout even though it may have linebreaks in Zotero. Structured abstracts with headings tend to cause this issue. The workaround is achieved by replacing linebreaks with a single space.

Screenshots

Info and abstract:

Comments and their nested highlights, with tags:

Folded headings

Theme

If someone is curious, the theme I am using in the screenshots is the Polka theme.

11 Likes

Thanks! I tried several templates before I found this one which I really like.
However, I have a question. I like the idea of grouping highlights by topic, but I want to try without the grouping. How can I cancel it?

Glad you liked it!

I haven’t tried that myself, but in that case, I would make a copy of the template, and then remove the macro for grouping, and then remove these two lines:

{% for color, annotations in annotations | groupby("color") -%}

### {{heading(color)}} <br>

and the last {% endfor -%}.

I think that should do the trick.

By making a copy, you can easily switch back to the template with grouping if you prefer that.

2 Likes

A neat trick if you want to define comments as tasks while annotating in Zotero is to change the comment line in the template to the following:
- {{annotation.comment|replace("todo ","[ ] ")}}:

Then, at the start of a comment which you want Zotero Integration to convert into a task, type todo. Any comment that starts with todo, will have the word todo replaced by square brackets [ ] , which turns it into a task according to markdown syntax, as the comments are already in a bullet list, so it becomes - [ ].

You can use any keyword you want to trigger this behavior, just change the template and workflow accordingly and replace todo with something else.

Note that I had to forgo making the comments bold for this to work. Maybe someone knows a workaround that could achieve both?

3 Likes

Hi, thanks for sharing a fascinating format! I do love it.

But, I am struggling with exchanging the position of annotation and comments.
For now, when I integrate Zotero into obsidian, my comment appears first followed by highlighted texts.

But, I want to make the highlighted texts come first and then my comments appear below since I don’t put comments for every highlighted text.

Could you help me with this?

1 Like

As is, the template should handle the absence of comments fine, because highlights without comments are listed un-indented.

But if you want comments below highlights, you can rearrange the template like so. I haven’t tested this, so please report back on how it works:

{%- for annotation in annotations -%}
{%- if annotation.imageRelativePath %}
![[{{annotation.imageRelativePath}}]]
{%- endif %}
{%- if annotation.comment %}
- =={{annotation.annotatedText | nl2br}}== [(p. {{annotation.pageLabel}})](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.pageLabel}}&annotation={{annotation.id}}) {% if annotation.hashTags %}{{annotation.hashTags}}
	- {{annotation.comment|replace("todo ","[ ] ")}}{% endif %}
{%- elif annotation.annotatedText %}
- =={{annotation.annotatedText | nl2br}}== [(p. {{annotation.pageLabel}})](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.pageLabel}}&annotation={{annotation.id}}) {% if annotation.hashTags %}{{annotation.hashTags}}{% endif %}

{%- endif -%}{%- endfor %}

{% endfor -%}
{% endif %}
{% endpersist %}
1 Like

@Gewerd - this may be a fix for your issue. I don’t make comments in Zotero, so that is uncharted territory for me

1 Like

[‘general.magenta’, ‘#e56eee’],

[‘general.orange’, ‘#f19837’],

[‘general.gray’, ‘#aaaaaa’]

1 Like

I have made a template by randomly combining all the templates above
after trial and error, it worked.

---
cssclass: 
- research-note
- wide-page 
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("Do MMM- YYYY")}}{% endif %}{% if archive %}
archive: "{{archive}}"{% endif %}{% if archiveLocation %}
archive-location: "{{archiveLocation}}"{% endif %}
citekey: {{citekey}}
---


[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 %}

### Index
start-date:: {% if date %}{{date | format("Do MMM- YYYY")}}{% endif %}
end-date::
## Annotations
{% persist "annotations" %}
{% set annots = annotations | filterby("date", "dateafter", lastImportDate) -%}
{% if annots.length > 0 %}
{% for annot in annots -%}

{#-**Annotations that start with #, to be turned into markdown style section headers**-#}
{% if annot.annotatedText and "#" in annot.annotatedText %}
{{annot.annotatedText|nl2br|lower|title}}

{#-**Regular text annotations w/ page number and page link**-#}
{%- elif annot.annotatedText %}

- <mark style="background: {{annot.color}}">{{annot.annotatedText | nl2br}}</mark>  [(pg. {{annot.page}})](zotero://open-pdf/library/items/{{annot.attachment.itemKey}}?page={{annot.page}}) {#**page link**#}

{%- endif -%}

{#-**Image annotations**-#}
{%- if annot.imageRelativePath %}
 ![[{{annot.imageRelativePath}}]]
{%- endif %}

{#-**comment annotations**-#}
{%- if annot.comment %}
>[!annot] Comment
>{{annot.comment | nl2br}}
 {%- endif %}

{%- endfor %}
{%- endif -%}
{%- endpersist -%}

6 Likes

it needs highlighter plugin to work
and the output is this:

2 Likes

I just noticed that this template doesn’t grab the “item notes” from zotero (these are the notes that you write in the sidebar, not related to a specific highlights, see attached screenshot, on the right side). Do you know how to grab those as well?

Yeah, I don’t make standalone notes in Zotero, so I left that out. I see someone on Discord already gave you the answer. The only thing you need to do is remove {{formattedAnnotations}} from their solution. That’s what “brought everything”. So the solution is:

{%- if markdownNotes %}
{{markdownNotes}}
{%- endif -%}

This could be answered by using the built-in Data Explorer command that Zotero Integration provides, in combination with the templating guide for Zotero Integration.

1 Like

ohhh that works. thanks!

Nice! Now that I see it, the reversion of importance, if I can call it that, makes total sense: in the source, your comment is secondary in the sense that it is a comment triggered by something in the text. But when you bring it into Obsidian (which is primarily about your own thinking) that comment becomes the primary thing and the text that triggered it is added for context.

And the bullet list format is much easier to handle than the callout format I’ve been using so far. Including the ingenious idea with the todo items!

The only thing I’ll have to think about before adopting this template are the colours. Currently, I have the callouts in the same colour as the original highlights, which helps for recognition. Unfortunately, Obsidian doesn’t support multiple highlighting colours, but I found the highlightr plugin which adds exactly that.

Not sure I want to add another plugin, though,… Another disadvantage of highlighting all the highlights in obsidian (regardless of colour) is that I can’t highlight parts of the highlight later in. This is something I do quite often when going through my annotations, to make it easier to quickly grasp the core point of the highlight.

Okay, think I’ll stop my thinking-out-loud here. Just wanted to highlight the ingenuity of this solution.

If anybody has adapted the zettelizer macro to turn each bullet point into a separate note (see here), please post it here!

Or perhaps it is easier to adjust the Zotero integration template so that it adds a heading before each annotation (which the is what the Zettelizer macro uses to extract notes)?

In fact, yes, I think that’s actually the way to go, because that way I can make sure that only annotations in a certain colour will be turned into notes, or, even better: only the ones that have comments. yay!

Wow, I just wanted to write a quick response and figure things out later, but it looks like writing that quick response made me figure stuff out. Writing is thinking.

1 Like

Thanks for sharing the highlighting. One question: how do I get black text in the highlighted portion? My text is showing up white which is tough to read.