- ZI-main.md
- The main Zotero Integration template
- runImport.md
- Template that enables updating literature notes at the click of a button, and much more.
- Meta bind button template
- Template for in-note button that executes runImport.md
-
-
Save FeralFlora/78f494c1862ce4457cef28d9d9ba5a01 to your computer and use it in GitHub Desktop.
<%* // Get citekey from 'citekey' property, or alias starting with '@' or file name const citekey = tp.frontmatter?.citekey || tp.frontmatter.aliases?.find(alias => alias.startsWith('@')) || tp.file.title; // Get the library ID from the properties. Fall back to "My Library" (1), if the library ID is not accessible const libraryID = tp.frontmatter.libraryID || 1; // Run the import app.plugins.getPlugin('obsidian-zotero-desktop-connector').runImport('IMPORT NAME', citekey, libraryID); ; %>
citekey: {{citekey}} aliases:
- "{%- if creators -%} {{creators[0].lastName or creators[0].name }} {%- if creators|length == 2 %} & {{creators[1].lastName or creators[1].name}}{% endif -%} {%- if creators|length > 2 %} et al.{% endif -%} {%- endif -%} {%- if date %} ({{date | format("YYYY")}}){% endif -%} {%- if shortTitle %} {{shortTitle | safe}} {%- else %} {{title | safe}} {%- endif -%}"{% if itemType == "bookSection" %} book-title: "{{bookTitle | replace('"',"'")}}"{% endif %} title: "{{title | replace('"',"'")}}" {%- set camelRegex = r/([a-z])([A-Z])/g %} {%- for type, creators in creators | groupby("creatorType") %} {% if creators.length > 1 %}{{type | replace(camelRegex, "$1 $2") | lower | trim}}s:{%- for creator in creators %}{% if creator.name %}
- {{creator.name}}{% else%}
- {{creator.firstName}} {{creator.lastName}} {% endif %}{%- endfor %} {% else -%} {{type | replace(camelRegex, "$1-$2") | lower | trim}}:{%- for creator in creators %}{% if creator.name %} "{{creator.name}}"{% else%} "{{creator.firstName}} {{creator.lastName}}"{% endif -%}{%- endfor -%}{% endif -%}{% endfor %} year: {% if date %}{{date | format("YYYY")}}{% endif %} item-type: {{itemType | replace(camelRegex, "$1 $2") | title | trim}} publisher: {% if publicationTitle %}"{{publicationTitle}}"{% else %}"{{publisher}}"{% endif %} {%- if notes.length > 0 -%} {%- set longShortCutoff = 20 -%} {%- set shortnotes = [] -%} {%- set longnotes = [] -%} {%- for note in notes -%} {%- if note.note | wordcount <= longShortCutoff -%} {%- set shortnotes = (shortnotes.push(note.note), shortnotes) -%} {%- else -%} {%- set longnotes = (longnotes.push(note), longnotes) -%} {%- endif -%}{%- endfor -%}{%- endif -%} {%- for comment in shortnotes %} {%- if comment and loop.first %} comments: {% endif -%}
- "{{comment|replace('"',"'")| replace("\n"," ")}}"{% endfor %} tags:{% for t in tags %}
- {{t.tag | replace(r/\s+/g, "-")}}{% endfor %}{% if DOI %} doi: https://doi.org/{{DOI}}{% endif %}{% if itemType == "book" %} ISBN: {{ISBN}}{% endif %} cssclasses:
- literature-note{% if attachments.length > 0 %}{% for attachment in attachments %}{% if loop.first %} attachments:{% endif %}
- {{attachment.path}}{% endfor %}{% endif %} libraryID: {{libraryID}}
BUTTON[update-litnote]
{% persist "notes" -%} {%- if isFirstImport %}
{# ==The following sections (Key takeaways and Processing) are not filled automatically. They are for for you to write into manually.== -#}
{#- The following is a cursor placeholder for the Templater plugin. After importing the note, you can jump to each of these with an assigned hotkey like ctrl+J #}
- <% tp.file.cursor(1) %>
- Status:: new
- Connections:: <% tp.file.cursor(4) %>
- Projects::
{% endif %}{% endpersist %}
[!info]- Info π Zotero{% if DOI %} | DOI{% endif %}{% for attachment in attachments | filterby("path", "endswith", ".pdf") %} | [PDF-{{loop.index}}](file:///{{attachment.path | replace(" ", "%20")}}){%- endfor %}
{% if bibliography %}Bibliography: {{bibliography|replace("\n","" )}}{% endif %}
Authors:: {% for a in creators %} [[03 - Source notes/People/{{a.firstName}} {{a.lastName}}|{{a.firstName}} {{a.lastName}}]]{% if not loop.last %}, {% endif %}{% endfor %}
{% if tags %}Tags: {% for t in tags %}#{{t.tag | replace(r/\s+/g, "-")}}{% if not loop.last %}, {% endif %}{% endfor %}{% endif %}
Collections:: {% for collection in collections %}[[{{collection.name}}]]{% if not loop.last %}, {% endif %}{% endfor -%} {%- set readingSpeed = 220 %} {%- set wordsPerPage = 360 %} {%- if pages %} {%- set pageRegex = r/(\d+)-(\d+)/ %} {%- set splitPages = pageRegex.test(pages) %} {%- if splitPages %} {%- set pageMatch = pageRegex.exec(pages) %} {%- set firstPage = pageMatch[1] %} {%- set pageCount = pageMatch[2] - pageMatch[1] %} {%- else %} {%- set pageCount = pages %} {%- endif %} {%- elif numPages %} {%- set pageCount = numPages %} {%- else %} {%- set pageCount = 0 %} {% endif -%} {%- if firstPage %}
First-page:: {{firstPage}} {%- endif -%} {%- if pageCount > 0 -%} {%- set readingTime = ((pageCount* wordsPerPage)/readingSpeed)/60 %}
Page-count:: {{pageCount}}
Reading-time:: {% if readingTime < 1 %}{{(readingTime * 60) | round + " minutes"}}{% else %}{{readingTime | round(3) + " hours"}}{% endif %}{% endif %}
[!abstract]- {% if abstractNote %} {{abstractNote|replace("\n","\n>")|striptags(true)|replace("Objectives", "Objectives")|replace("Background", "Background")|replace("Methodology", "Methodology")|replace("Results","Results")|replace("Conclusion","Conclusion")}} {% endif %}
[!quote]- Citations
content: "@{{citekey}}" -file:@{{citekey}}
{%- set headingRegex = r/^#+/ -%} {%- set titleRegex = r/^#+./ -%} {%- set lineRegex = r/^.$/m %} {%- if longnotes.length > 0 -%} {%- for n in longnotes -%} {%- if n and loop.first %}
[!note]- Zotero notes ({{longnotes.length}})
Notes longer than {{longShortCutoff}} words. {%- endif %}
[!example]- Note {{loop.index}} |{%- if headingRegex.test(n.note) == true %}{{n.note | replace(n.note,titleRegex.exec(n.note))|replace(headingRegex,"")}}{% else %} {{lineRegex.exec(n.note | truncate(30))}} {% endif %} {{n.note | replace("\n", "\n>> ")| replace(titleRegex, "")}}{% if n.tags.length > 0 %}
Tags:{% for t in n.tags %} #{{t.tag}}{% if not loop.last %}, {% endif %}{% endfor %}{% endif -%}{%- if not loop.last %} {%- endif -%} {%- endfor -%}{%- endif %}
{% set colorValueMap = { "#2ea8e5": { "colorCategory": "Blue", "heading": "β Problem formulation", "symbol": "?" }, "#5fb236": { "colorCategory": "Green", "heading": "π― Key takeaways", "symbol": "$" }, "#ffd400": { "colorCategory": "Yellow", "heading": "π¬ Evidence and arguments", "symbol": "&" }, "#f19837": { "colorCategory": "Orange", "heading": "β Actionable takeaways", "symbol": "!" }, "#a28ae5": { "colorCategory": "Purple", "heading": "π§© Concepts and frameworks", "symbol": "~" }, "#e56eee": { "colorCategory": "Magenta", "heading": "πΊοΈ Context and connections", "symbol": "β¬" }, "#ff6666": { "colorCategory": "Red", "heading": "π§ Digging and disclaimers", "symbol": "Β£" }, "#aaaaaa": { "colorCategory": "Gray", "heading": "π Statistics and info", "symbol": "%" } } -%}
{%- macro tagFormatter(annotation) -%} {% if annotation.tags -%} {%- for t in annotation.tags %} #{{ t.tag | replace(r/\s+/g, "-") }}{% if not loop.last %}, {% endif %}{%- endfor %} {%- endif %} {%- endmacro -%}
{% persist "annotations" %} {% set annotations = annotations | filterby("date", "dateafter", lastImportDate) -%} {% if annotations.length > 0 %} Imported on [[{{importDate | format("YYYY-MM-DD")}}]] at {{importDate | format("HH:mm")}}
{%- set grouped_annotations = annotations | groupby("color") -%} {%- for color, colorValue in colorValueMap -%} {%- if color in grouped_annotations -%} {%- set annotations = grouped_annotations[color] -%} {%- for annotation in annotations -%} {%- set citationLink = '[(p. ' ~ annotation.pageLabel ~ ')](' ~ annotation.desktopURI ~ ')' %} {%- set tagString = tagFormatter(annotation) %}
{%- if annotation and loop.first %}
{% endif -%}
{%- if annotation.imageRelativePath %}
[!cite]+ Image {{citationLink}} ![[{{annotation.imageRelativePath}}]]{% if annotation.tags %} {{tagString}}{% endif %}{%- if (annotation.comment or []).indexOf("todo ") !== -1 %}
- {{annotation.comment | replace("todo ", "")}}{%- elif annotation.comment %} {{annotation.comment}}{%- endif %} {% elif (annotation.comment or []).indexOf("todo ") !== -1 %}
- {{annotation.comment | replace("todo ", "")}}:{% if not annotation.annotatedText %} {{citationLink}}{% else %}
- {{colorValue.symbol}} {{annotation.annotatedText | replace(r/\s+/g, " ")}} {{citationLink}}{{tagString}}{% endif -%} {% elif annotation.comment %}
- {{annotation.comment}}:{% if not annotation.annotatedText %} {{citationLink}}{% else %}
- {{colorValue.symbol}} {{annotation.annotatedText | replace(r/\s+/g, " ") }} {{citationLink}}{{tagString}}{% endif -%} {%- elif annotation.annotatedText %}
- {{colorValue.symbol}} {{annotation.annotatedText | replace(r/\s+/g, " ") }} {{citationLink}}{{tagString}} {%- endif -%}{%- endfor %}{%- endif -%} {% endfor -%} {% endif %}
{% endpersist %}
Could you kindly explain how switch your highlight output (annotation) vs your comments in the template. I noted your post suggesting this (string below) but which lines of the code need to be swapped? I often put sources in my comments and they're numbered so its messing up the colored highlighting. Thanks!
{%- for annotation in annotations -%}
{%- if annotation.imageRelativePath %}
![[{{annotation.imageRelativePath}}]]
{%- endif %}
{%- if annotation.comment %}
- =={{annotation.annotatedText | nl2br}}== (p. {{annotation.pageLabel}}) {% if annotation.hashTags %}{{annotation.hashTags}}
- {{annotation.comment|replace("todo ","[ ] ")}}{% endif %}
{%- elif annotation.annotatedText %}
- {{annotation.comment|replace("todo ","[ ] ")}}{% endif %}
- =={{annotation.annotatedText | nl2br}}== (p. {{annotation.pageLabel}}) {% if annotation.hashTags %}{{annotation.hashTags}}{% endif %}
{%- endif -%}{%- endfor %}
{% endfor -%}
{% endif %}
{% endpersist %}
@FeralFlora, I just wanted to reach out to thank you for the detailed explanations and well considered questions that you have posted over various forums - your questions and answers have repeatedly popped up for the same reasons along my Zotero > Obsidian > Pandoc > Typst/Rstudio/Quatro journey whilst trying to understand how these systems could fit together and replace my Microsoft apps and systems (whilst also trying to avoid the potential need to learn LaTex). Fittingly, this template served as the final piece joining the results of my efforts on each end together... and today being the final day I had given myself. Now I'm off to create some unpleasant beautiful documents.