diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..722d5e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode diff --git a/README.md b/README.md new file mode 100644 index 0000000..f2e85b5 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# Obsidian Templates + +This is a collection of [Obsidian](https://obsidian.md/) templates I use or have used. Most of these use Templater (and its "Trigger on file creation" feature) but I'll list the plugins used for each one in the [overview below](#overview). You might also need to adjust folder paths and file names used in the Templater scripts. I've translated some metadata field names to English for readability. + +## Overview + +- [book.md](book.md) + - Add a book to your vault + - Plugins: Templater, Book Search +- [callouts.md](callouts.md) + - Choose one of the default callouts to insert at your cursor + - Plugins: Templater +- [include.md](include.md) + - Insert the content of a note at your cursor + - Plugins: Templater +- [lecture.md](lecture.md) + - Create a lecture (session) note + - Plugins: Templater +- [meeting.md](meeting.md) + - Create a meeting note for today/yesterday/tomorrow, select a project from a folder + - Plugins: Templater +- [movie.md](movie.md) + - Similar to the book template, add a movie (or TV show) to your vault + - Plugins: Templater, QuickAdd (plus this script and the setup for it: ) +- [open-daily.md](open-daily.md) + - Open today's daily note (extremely basic, no error handling) + - Plugins: Templater +- [wikilink.md](wikilink.md) + - Insert a wikilink to a note + - Plugins: Templater +- [workbench.md](workbench.md) + - Adds the current selection to a "workbench" note as a bullet point with today's date + - Plugins: Templater, Workbench (optional) +- [youtube.md](youtube.md) + - Gets metadata from a YouTube video and embeds it, works by copying the video ID to the clipboard + - Plugins: Templater +- [zettel.md](zettel.md) + - Basic Zettelkasten template, asks for the type of the Zettel (I differentiate claims from concepts and questions) + - Plugins: Templater +- [zotero.md](zotero.md) + - Create a literature note from a Zotero item, pulling some metadata and all your PDF annotations + - Plugins: Zotero Integration diff --git a/book.md b/book.md new file mode 100644 index 0000000..efb6e62 --- /dev/null +++ b/book.md @@ -0,0 +1,18 @@ +<% "---" %> +tags: πŸ“₯/πŸ“š +type: # fiction or nonfiction +pages: {{totalPage}} +fileclass: book +title: "{{title}}" +created: <% tp.file.creation_date("YYYY-MM-DD") %> +modified: <% tp.file.last_modified_date("YYYY-MM-DD") %> +cover: {{coverUrl}} +<% "---" %> + +![cover|150]({{coverUrl}}) + +> [!meta]+ Metadaten +> - Author:: {{authors}} +> - Year:: {{publishDate}} +> - Status:: +> - Read:: \ No newline at end of file diff --git a/callouts.md b/callouts.md new file mode 100644 index 0000000..61b0dc9 --- /dev/null +++ b/callouts.md @@ -0,0 +1,12 @@ +<%* +// Choose a callout from a suggester +// Grouped by color + +const types = ["🟦", "Note", "Abstract", "Summary", "TLDR", "Info", "Todo", "Tip", "Hint", "Important", "🟩", "Success", "Check", "Done", "Question", "Help", "FAQ", "🟨", "Warning", "Caution", "Attention", "🟧", "Failure", "Fail", "Missing", "πŸŸ₯", "Danger", "Error", "Bug", "πŸŸͺ", "Example", "⬛️", "Quote", "Cite"]; + +const callouts = ["Blue", "> [!note]", "> [!abstract]", "> [!summary]", "> [!tldr]", "> [!info]", "> [!todo]", "> [!tip]", "> [!hint]", "> [!important]", "Green", "> [!success]", "> [!check]", "> [!done]", "> [!question]", "> [!help]", "> [!faq]", "Yellow", "> [!warning]", "> [!caution]", "> [!attention]", "Orange", "> [!failure]", "> [!fail]", "> [!missing]", "Red", "> [!danger]", "> [!error]", "> [!bug]", "Pink", "> [!example]", "Black", "> [!quote]", "> [!cite]"]; + +let suggest = await tp.system.suggester(types, callouts); +if (suggest == "null" || /Blue|Green|Yellow|Orange|Red|Pink|Black/.test(suggest)) {return ""}; +return suggest; +%> \ No newline at end of file diff --git a/include.md b/include.md new file mode 100644 index 0000000..1535aa8 --- /dev/null +++ b/include.md @@ -0,0 +1,7 @@ +<%* +// Choose file in vault to include its content in the current note + +const files = this.app.vault.getMarkdownFiles() +const file = await tp.system.suggester((files) => files.basename, files) +tR += await tp.file.include("[[" + file.basename + "]]") +%> \ No newline at end of file diff --git a/lecture.md b/lecture.md new file mode 100644 index 0000000..0ddc52e --- /dev/null +++ b/lecture.md @@ -0,0 +1,35 @@ +<% "---" %> +tags: πŸŽ“/πŸ“ +created: <% tp.file.creation_date("YYYY-MM-DD") %> +modified: <% tp.file.last_modified_date("YYYY-MM-DD") %> +<% "---" %> +<%* +const newDate = await tp.date.now("YYYY-MM-DD"); + +const files = this.app.vault.getMarkdownFiles() + // Filter by folder + .filter(file => file.path.match("20 Studium/26")) + .sort((a, b) => a.basename.localeCompare(b.basename)); + +// Further filter by tag +const filesWithTags = files.filter(file => app.metadataCache.getFileCache(app.vault.getAbstractFileByPath(file.path)).frontmatter?.tags?.includes("πŸŽ“/πŸ“Œ")); + +const fileNames = filesWithTags.map(file => file.basename); +const filePaths = filesWithTags.map(file => file.path); + +const courseFolder = await tp.system.suggester(fileNames, filePaths.map(folder => folder.split("/").slice(0,3).join("/")), true); + +const newPath = courseFolder + "/Sessions/" + newDate; +await tp.file.move(newPath); + +const courseName = filesWithTags.filter(file => file.path.includes(courseFolder)).map(file => file.basename); + +-%> + +<%* +// Un-escape wikilinks +let content = "↑ LV:: \[\[" + courseName + "\]\]"; +const replaced = content.replace(/\\/g, ""); +tR += replaced; +-%> +<% tp.file.cursor(0) %> \ No newline at end of file diff --git a/meeting.md b/meeting.md new file mode 100644 index 0000000..3b828e5 --- /dev/null +++ b/meeting.md @@ -0,0 +1,31 @@ +<%"---"%> +tags: πŸ’»/πŸ“… +created: <% tp.file.creation_date("YYYY-MM-DD") %> +modified: <% tp.file.last_modified_date("YYYY-MM-DD") %> +<%"---"%> +<%* +const days = ["today", "yesterday", "tomorrow"] +const dateValue = await tp.system.suggester(days, days, true) +const newDate = app.plugins.plugins['nldates-obsidian'].parseDate(dateValue).moment.format("YYYY-MM-DD"); +const tag = "#πŸ’»/🎯" +const files = this.app.vault.getMarkdownFiles() + .filter(file => file.path.match("30 Job")) + .filter(file => { + const tags = tp.obsidian.getAllTags(app.metadataCache.getFileCache(file)); + return tags.includes(tag);}) + .sort((a, b) => a.basename.localeCompare(b.basename)); +const project = (await tp.system.suggester((file) => file.basename, files)).basename; +const newPath = "30 Job/31 Meetings/" + newDate + " " + project; +await tp.file.move(newPath); +-%> + +↑ [[<% project %>]] + +### Prep +- <% tp.file.cursor(0) %> + +### Notes +- + +### Follow-up +- \ No newline at end of file diff --git a/movie.md b/movie.md new file mode 100644 index 0000000..df83bcd --- /dev/null +++ b/movie.md @@ -0,0 +1,21 @@ +<% "---" %> +tags: πŸ“₯/πŸ“€ +fileclass: movie +cover: {{VALUE:Poster}} +created: <% tp.file.creation_date("YYYY-MM-DD") %> +modified: <% tp.file.last_modified_date("YYYY-MM-DD") %> +<% "---" %> + +> {{VALUE:Plot}} + +![|200]({{VALUE:Poster}}) + + +--- + +> [!meta]+ Metadaten +> - Year:: {{VALUE:Year}} +> - Genre:: {{VALUE:Genre}} +> - Language:: {{VALUE:Language}} +> - Status:: to-watch +> - Watched:: \ No newline at end of file diff --git a/open-daily.md b/open-daily.md new file mode 100644 index 0000000..4ee563d --- /dev/null +++ b/open-daily.md @@ -0,0 +1,5 @@ +<%* +// Get daily note and open it in a new leaf, fails if note doesn't exist... but I'm lazy + +return app.workspace.getLeaf(true, 'vertical').openFile(app.vault.getAbstractFileByPath("50 Periodic/" + moment().format("YYYY") + "/" + moment().format("YYYY-MM-DD") + ".md")) +%> \ No newline at end of file diff --git a/wikilink.md b/wikilink.md new file mode 100644 index 0000000..43dd785 --- /dev/null +++ b/wikilink.md @@ -0,0 +1,5 @@ +<%* +const files = this.app.vault.getMarkdownFiles() +const file = await tp.system.suggester((files) => files.basename, files) +tR += "[[" + file.basename + "]]" +%> \ No newline at end of file diff --git a/workbench.md b/workbench.md new file mode 100644 index 0000000..6c85d9d --- /dev/null +++ b/workbench.md @@ -0,0 +1,10 @@ +<%* +const selection = tp.file.selection() +const workbench = tp.file.find_tfile("Workbench") // Name of your Workbench file +if (selection) { + // New line, bullet point with today's date prepended + const line = "\n- " + tp.date.now("YYYY-MM-DD ") + selection.split("\n").join(" ") + await app.vault.append(workbench, line) +} +tR += selection +%> \ No newline at end of file diff --git a/youtube.md b/youtube.md new file mode 100644 index 0000000..45a4dbc --- /dev/null +++ b/youtube.md @@ -0,0 +1,34 @@ +<%"---"%> +tags: πŸ“₯/πŸ“Ή +created: <% tp.file.creation_date("YYYY-MM-DD") %> +modified: <% tp.file.last_modified_date("YYYY-MM-DD") %> +<%"---"%> +<%* +const url = await tp.system.clipboard() +const response = await fetch(`https://youtube.com/oembed?url=${url}&format=json`) +const data = await response.json() +console.log(data) + +// Create a safe title... there's probably a better way to do this +const title = data.title.replaceAll("", "").replaceAll('"', '').replaceAll("\\", "").replaceAll("/", "").replaceAll("<", "").replaceAll(">", "").replaceAll(":", "").replaceAll("|", "").replaceAll("?", "") +const author = data.author_name +const author_url = data.author_url +const html = data.html + +// Change target path to whatever, has to exist (I think; read the Templater docs) +const newPath = "40 Media/" + title +await tp.file.move(newPath) +const regex = /v=(.*)/gm +const m = regex.exec(url) +-%> + +> [!meta]+ Metadaten +> Source:: [<% title %>](<% url %>) +> Channel: [<% author %>](<% author_url %>) +> Published: +> Watched: <% tp.date.now() %> + +<% tp.file.cursor(0) %> + +--- + \ No newline at end of file diff --git a/zettel.md b/zettel.md new file mode 100644 index 0000000..8648135 --- /dev/null +++ b/zettel.md @@ -0,0 +1,14 @@ +<% "---" %> +lang: # de, en +tags: + - πŸ—ƒ<% await tp.system.suggester(["Concept", "Claim", "Question"], ["/πŸ’ ", "/🌱", "/❓"])%> +title: "<% tp.file.title %>" +date: <% tp.file.creation_date("YYYY-MM-DD") %> +lastmod: <% tp.file.last_modified_date("YYYY-MM-DD") %> +<% "---" %> + +<% tp.file.cursor(0) %> + +- Keywords:: +- Quelle: +- Siehe: \ No newline at end of file diff --git a/zotero.md b/zotero.md new file mode 100644 index 0000000..5220571 --- /dev/null +++ b/zotero.md @@ -0,0 +1,121 @@ +--- +tags: {%- if itemType == "book" %} + - πŸ“₯/πŸ“š{% else %} + - πŸ“₯/πŸ“‘{% endif %} +alias: " + {%- if creators -%} + {{creators[0].lastName}} + {%- if creators|length > 1 %} et al.{% endif -%} + {%- endif -%} + {%- if date %} ({{date | format("YYYY")}}){% endif -%} + {%- if shortTitle %} {{shortTitle | safe}} {%- else %} {{title | safe}} {%- endif -%} +" +date: {{importDate|format("YYYY-MM-DD")}} +lastmod: {{importDate|format("YYYY-MM-DD")}} +--- +{% if isFirstImport %} +# {{title}} + +## πŸ“‡ Index +- + +> [!meta]+ Metadaten – {% for attachment in attachments | filterby("path", "endswith", ".pdf") %}[PDF{% if not loop.first %} {{loop.index}}{% endif %}]({{attachment.desktopURI|replace("/select/", "/open-pdf/")}}){% if not loop.last %}, {% endif %}{% endfor %} +> {{bibliography}} +> +> - **Projekte**:: +> - **Keywords**:: +> - [Zotero ΓΆffnen]({{select}}) +> {% endif %}{% persist "annotations" %} + +{%- + set zoteroColors = { + "#2ea8e5": "blue", + "#5fb236": "green", + "#a28ae5": "purple", + "#ffd400": "yellow", + "#ff6666": "red", + "#f19837": "orange", + "#e56eee": "magenta", + "#aaaaaa": "grey" + } +-%} + +{%- + set colorHeading = { + "blue": "⭐ Main", + "green": "βœ… Definition", + "purple": "🧩 Methodology", + "yellow": "πŸ“š Investigate", + "red": "β­• Caveats/Lookup", + "other": "Misc" + } +-%} + +{%- macro calloutHeader(type) -%} + {%- switch type -%} + {%- case "highlight" -%} + Highlight + {%- case "image" -%} + Image + {%- default -%} + Note + {%- endswitch -%} +{%- endmacro %} + +{%- set newAnnot = [] -%} +{%- set newAnnotations = [] -%} +{%- set annotations = annotations | filterby("date", "dateafter", lastImportDate) %} + +{% if annotations.length > 0 %} +*Imported: {{importDate | format("YYYY-MM-DD HH:mm")}}* + +{%- for annot in annotations -%} + + {%- if annot.color in zoteroColors -%} + {%- set customColor = zoteroColors[annot.color] -%} + {%- elif annot.colorCategory|lower in colorHeading -%} + {%- set customColor = annot.colorCategory|lower -%} + {%- else -%} + {%- set customColor = "other" -%} + {%- endif -%} + + {%- set newAnnotations = (newAnnotations.push({"annotation": annot, "customColor": customColor}), newAnnotations) -%} + +{%- endfor -%} + +{#- INSERT ANNOTATIONS -#} +{#- Loops through each of the available colors and only inserts matching annotations -#} +{#- This is a workaround for inserting categories in a predefined order (instead of using groupby & the order in which they appear in the PDF) -#} + +{%- for color, heading in colorHeading -%} +{%- for entry in newAnnotations | filterby ("customColor", "startswith", color) -%} +{%- set annot = entry.annotation -%} + +{%- if entry and loop.first %} + +### {{colorHeading[color]}} +{%- endif %} + +> [!quote{{"|" + color if color != "other"}}]+ {{calloutHeader(annot.type)}} ([p. {{annot.pageLabel}}](zotero://open-pdf/library/items/{{annot.attachment.itemKey}}?page={{annot.pageLabel}}&annotation={{annot.id}})) + +{%- if annot.annotatedText %} +> {% if annot.hashTags %}[[{{annot.hashTags|replace("#", "")}}]]: {% endif -%} +{{annot.annotatedText|nl2br}} +{%- endif %} + +{%- if annot.imageRelativePath %} +> ![[{{annot.imageRelativePath}}]] +{%- endif %} + +{%- if annot.ocrText %} +> {{annot.ocrText}} +{%- endif %} + +{%- if annot.comment %} +> **{{annot.comment|nl2br}}** +{%- endif -%} + +{%- endfor -%} +{%- endfor -%} +{% endif %} +{% endpersist -%} \ No newline at end of file